-
-
Notifications
You must be signed in to change notification settings - Fork 456
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Run prettier instance in worker_threads
#3016
Changes from 23 commits
fe36bd8
89adebf
50e9c19
ff49d1f
ff3da84
1692842
242489b
b4f151e
1681bc3
87faf54
0b7305e
a6d6a8e
419a3e4
6052ff6
11db0da
b8ac001
c9c7477
7b95303
5b7bbcb
a8e5a6a
9414fd9
39eaff0
9b8ca48
93d8f71
9b33cd4
f8f51be
7ff3997
bd30842
ac6e320
a80d6bc
e858752
f1cda05
4c1fdc8
901d664
6b43bfe
eaf9e2f
941d91b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
/src/worker/*.js |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
import { Worker } from "worker_threads"; | ||
import * as url from "url"; | ||
import * as path from "path"; | ||
import { | ||
PrettierFileInfoOptions, | ||
PrettierFileInfoResult, | ||
PrettierOptions, | ||
PrettierSupportLanguage, | ||
} from "./types"; | ||
|
||
const worker = new Worker( | ||
url.pathToFileURL(path.join(__dirname, "/worker/prettier-instance-worker.js")) | ||
); | ||
|
||
export class PrettierWorkerInstance { | ||
private importResolver: { | ||
resolve: (version: string) => void; | ||
reject: (version: string) => void; | ||
} | null = null; | ||
|
||
private callMethodResolvers: { | ||
id: number; | ||
resolve: (value: unknown) => void; | ||
reject: (value: unknown) => void; | ||
}[] = []; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe we can use
to
|
||
|
||
private currentCallMethodId = 0; | ||
|
||
public version: string | null = null; | ||
|
||
constructor(private modulePath: string) { | ||
worker.on("message", ({ type, payload }) => { | ||
switch (type) { | ||
case "import": { | ||
this.importResolver?.resolve(payload.version); | ||
this.version = payload.version; | ||
break; | ||
} | ||
case "callMethod": { | ||
const resolver = this.callMethodResolvers.find(({ id }) => { | ||
return id === payload.id; | ||
}); | ||
if (resolver) { | ||
if (payload.isError) { | ||
resolver.reject(payload.result); | ||
} else { | ||
resolver.resolve(payload.result); | ||
} | ||
} | ||
break; | ||
} | ||
} | ||
}); | ||
} | ||
|
||
public async import(): Promise</* version of imported prettier */ string> { | ||
const promise = new Promise<string>((resolve, reject) => { | ||
this.importResolver = { resolve, reject }; | ||
}); | ||
worker.postMessage({ | ||
type: "import", | ||
payload: { modulePath: this.modulePath }, | ||
}); | ||
return promise; | ||
} | ||
|
||
public async format( | ||
source: string, | ||
options?: PrettierOptions | ||
): Promise<string> { | ||
const result = this.callMethod("format", [source, options]); | ||
return result; | ||
} | ||
|
||
public async getSupportInfo(): Promise<{ | ||
languages: PrettierSupportLanguage[]; | ||
}> { | ||
const result = await this.callMethod("getSupportInfo", []); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why these two methods, one |
||
return result; | ||
} | ||
|
||
public async clearConfigCache(): Promise<void> { | ||
await this.callMethod("clearConfigCache", []); | ||
} | ||
|
||
public async getFileInfo( | ||
filePath: string, | ||
fileInfoOptions?: PrettierFileInfoOptions | ||
): Promise<PrettierFileInfoResult> { | ||
const result = await this.callMethod("getFileInfo", [ | ||
filePath, | ||
fileInfoOptions, | ||
]); | ||
return result; | ||
} | ||
|
||
private callMethod(methodName: string, methodArgs: unknown[]): Promise<any> { | ||
const callMethodId = this.currentCallMethodId++; | ||
// log(JSON.stringify({ methodName, methodArgs, callMethodId })); | ||
const promise = new Promise((resolve, reject) => { | ||
this.callMethodResolvers.push({ id: callMethodId, resolve, reject }); | ||
}); | ||
worker.postMessage({ | ||
type: "callMethod", | ||
payload: { | ||
id: callMethodId, | ||
modulePath: this.modulePath, | ||
methodName, | ||
methodArgs, | ||
}, | ||
}); | ||
return promise; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -54,7 +54,11 @@ export function putBackPrettierRC(done: Done) { | |
* @param base base URI | ||
* @returns source code and resulting code | ||
*/ | ||
export async function format(workspaceFolderName: string, testFile: string) { | ||
export async function format( | ||
workspaceFolderName: string, | ||
testFile: string, | ||
shouldRetry = false | ||
) { | ||
const base = getWorkspaceFolderUri(workspaceFolderName); | ||
const absPath = path.join(base.fsPath, testFile); | ||
const doc = await vscode.workspace.openTextDocument(absPath); | ||
|
@@ -70,10 +74,23 @@ export async function format(workspaceFolderName: string, testFile: string) { | |
console.time(testFile); | ||
await vscode.commands.executeCommand("editor.action.formatDocument"); | ||
|
||
let actual = doc.getText(); | ||
|
||
if (shouldRetry) { | ||
for (let i = 0; i < 10; i++) { | ||
if (text !== actual) { | ||
break; | ||
} | ||
await wait(150); | ||
await vscode.commands.executeCommand("editor.action.formatDocument"); | ||
actual = doc.getText(); | ||
} | ||
} | ||
|
||
Comment on lines
+77
to
+89
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Some code, like PHP files, can take a bit of time, like opening a text editor and then requiring plugins and huge parsers. |
||
// eslint-disable-next-line no-console | ||
console.timeEnd(testFile); | ||
|
||
return { actual: doc.getText(), source: text }; | ||
return { actual, source: text }; | ||
} | ||
/** | ||
* Compare prettier's output (default settings) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can't really access all properties of the module. I'd do
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't really need to access any properties other than version, so I think we can leave it as is.