-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathjavaScriptFormatter.ts
More file actions
109 lines (86 loc) · 3.09 KB
/
javaScriptFormatter.ts
File metadata and controls
109 lines (86 loc) · 3.09 KB
1
2
3
4
5
6
7
8
9
10
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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
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
import {CodeFormatter, CodeFormatterError} from '@/application/project/code/formatting/formatter';
import {FileSystem} from '@/application/fs/fileSystem';
import {Dependency, PackageManager} from '@/application/project/packageManager/packageManager';
import {WorkingDirectory} from '@/application/fs/workingDirectory/workingDirectory';
import {SynchronousCommandExecutor} from '@/application/system/process/executor';
import {Command} from '@/application/system/process/command';
type FormatterTool = {
package: string,
bin?: string,
args(files: string[]): string[],
};
export type Configuration = {
workingDirectory: WorkingDirectory,
fileSystem: FileSystem,
packageManager: PackageManager,
commandExecutor: SynchronousCommandExecutor,
timeout?: number,
tools: FormatterTool[],
};
export class JavaScriptFormatter implements CodeFormatter {
private readonly configuration: Configuration;
public constructor(configuration: Configuration) {
this.configuration = configuration;
}
public async format(files: string[]): Promise<void> {
const command = await this.getCommand(files);
if (command === null) {
return;
}
try {
await this.run(command);
} catch {
// suppress
}
}
private run(command: Command): Promise<void> {
const {commandExecutor, workingDirectory, timeout} = this.configuration;
const execution = commandExecutor.runSync(command, {
workingDirectory: workingDirectory.get(),
timeout: timeout,
});
if (execution.exitCode !== 0) {
throw new CodeFormatterError('Failed to format code.');
}
return Promise.resolve();
}
private async getCommand(files: string[]): Promise<Command|null> {
const {tools, packageManager, fileSystem} = this.configuration;
for (const tool of tools) {
if (!await packageManager.hasDirectDependency(tool.package)) {
// Ensure the package is a direct dependency
continue;
}
const info = await packageManager.getDependency(tool.package);
if (info === null) {
continue;
}
const bin = JavaScriptFormatter.getBinPath(info, tool.bin);
if (bin === null) {
continue;
}
return {
name: fileSystem.joinPaths(info.directory, fileSystem.normalizeSeparators(bin)),
arguments: tool.args(files),
};
}
return null;
}
private static getBinPath({metadata}: Dependency, bin?: string): string|null {
if (!('bin' in metadata)) {
return null;
}
if (typeof metadata.bin === 'string') {
return metadata.bin;
}
if (
bin !== undefined
&& typeof metadata.bin === 'object'
&& metadata.bin !== null
&& typeof metadata.bin[bin] === 'string'
) {
return metadata.bin[bin];
}
return null;
}
}