|
1 | 1 | import path from 'path';
|
2 | 2 |
|
3 | 3 | import fs from 'fs-extra';
|
4 |
| -import { Options, check, format, getFileInfo, resolveConfig } from 'prettier'; |
| 4 | +import { |
| 5 | + Options, |
| 6 | + SupportLanguage, |
| 7 | + check, |
| 8 | + format, |
| 9 | + getSupportInfo, |
| 10 | + resolveConfig, |
| 11 | +} from 'prettier'; |
5 | 12 |
|
6 | 13 | import { crawlDirectory } from '../../utils/dir';
|
7 | 14 | import { Logger, pluralise } from '../../utils/logging';
|
8 | 15 | import { getConsumerManifest } from '../../utils/manifest';
|
9 | 16 |
|
| 17 | +let languages: SupportLanguage[] | undefined; |
| 18 | + |
| 19 | +/** |
| 20 | + * Infers a parser for the specified filepath. |
| 21 | + * |
| 22 | + * This is a cut-down version of Prettier's built-in function of the same name; |
| 23 | + * ours operates purely on the `filepath` string and does not perform file I/O. |
| 24 | + * Prettier's internal `getInterpreter` function can open a file to read the |
| 25 | + * shebang, and its file descriptor usage can throw warnings on worker threads: |
| 26 | + * |
| 27 | + * ```console |
| 28 | + * Warning: File descriptor 123 closed but not opened in unmanaged mode |
| 29 | + * at Object.closeSync (node:fs:530:11) |
| 30 | + * at Object.closeSync (node_modules/graceful-fs/graceful-fs.js:74:20) |
| 31 | + * ... |
| 32 | + * ``` |
| 33 | + * |
| 34 | + * References: |
| 35 | + * |
| 36 | + * - https://github.com/prettier/prettier/blob/2.4.1/src/main/options.js#L167 |
| 37 | + * - seek-oss/skuba#659 |
| 38 | + */ |
| 39 | +export const inferParser = (filepath: string): string | undefined => { |
| 40 | + const filename = path.basename(filepath).toLowerCase(); |
| 41 | + |
| 42 | + languages ??= getSupportInfo().languages.filter((language) => language.since); |
| 43 | + |
| 44 | + const firstLanguage = languages.find( |
| 45 | + (language) => |
| 46 | + language.extensions?.some((extension) => filename.endsWith(extension)) || |
| 47 | + language.filenames?.some((name) => name.toLowerCase() === filename), |
| 48 | + ); |
| 49 | + |
| 50 | + return firstLanguage?.parsers[0]; |
| 51 | +}; |
| 52 | + |
10 | 53 | interface File {
|
11 | 54 | data: string;
|
12 | 55 | options: Options;
|
@@ -110,12 +153,12 @@ export const runPrettier = async (
|
110 | 153 |
|
111 | 154 | for (const filepath of filepaths) {
|
112 | 155 | // Infer parser upfront so we can skip unsupported files.
|
113 |
| - const fileInfo = await getFileInfo(filepath, { resolveConfig: false }); |
| 156 | + const parser = inferParser(filepath); |
114 | 157 |
|
115 | 158 | logger.debug(filepath);
|
116 |
| - logger.debug(' parser:', fileInfo.inferredParser ?? '-'); |
| 159 | + logger.debug(' parser:', parser ?? '-'); |
117 | 160 |
|
118 |
| - if (!fileInfo.inferredParser) { |
| 161 | + if (!parser) { |
119 | 162 | result.unparsed.push(filepath);
|
120 | 163 | continue;
|
121 | 164 | }
|
|
0 commit comments