Skip to content

Commit effaa35

Browse files
committed
fix: windows support
1 parent 4565d90 commit effaa35

File tree

8 files changed

+97
-52
lines changed

8 files changed

+97
-52
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
# 1.6.7
2+
3+
- fix: windows support
4+
15
# 1.6.6
26

37
- fix: regression in nested swift projects #29

README.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -42,14 +42,14 @@ let package = Package(
4242

4343
## Configuration
4444

45-
| Config | Type | Default | Description |
46-
| ----------------------------------------- | ------------------- | ----------------------------- | ------------------------------------------------------------------------------------------ |
47-
| `swiftformat.enable` | `Bool` | `true` | Whether SwiftFormat should actually do something. |
48-
| `swiftformat.onlyEnableOnSwiftPMProjects` | `Bool` | `false` | Requires and uses a SwiftFormat as SwiftPM dependency. |
49-
| `swiftformat.onlyEnableWithConfig` | `Bool` | `false` | Only format if config present. |
50-
| `swiftformat.path` | `[String] | String` | `[/usr/bin/env, swiftformat]` | The location of the globally installed SwiftFormat. |
51-
| `swiftformat.options` | `[String]` | `[]` | Additional [options for SwiftFormat](https://github.com/nicklockwood/SwiftFormat#options). |
52-
| `swiftformat.configSearchPaths` | `[String]` | `[".swiftformat"]` | Possible paths for SwiftFormat config. |
45+
| Config | Type | Default | Description |
46+
| ----------------------------------------- | ---------- | ------------------ | ------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------- |
47+
| `swiftformat.enable` | `Bool` | `true` | Whether SwiftFormat should actually do something. |
48+
| `swiftformat.onlyEnableOnSwiftPMProjects` | `Bool` | `false` | Requires and uses a SwiftFormat as SwiftPM dependency. |
49+
| `swiftformat.onlyEnableWithConfig` | `Bool` | `false` | Only format if config present. |
50+
| `swiftformat.path` | `[String] | String` | `swiftformat` | The location of the globally installed SwiftFormat (resolved with the current path if only a filename). |
51+
| `swiftformat.options` | `[String]` | `[]` | Additional [options for SwiftFormat](https://github.com/nicklockwood/SwiftFormat#options). |
52+
| `swiftformat.configSearchPaths` | `[String]` | `[".swiftformat"]` | Possible paths for SwiftFormat config. |
5353

5454
## Contributors
5555

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"type": "git",
77
"url": "https://github.com/vknabel/vscode-swiftformat"
88
},
9-
"version": "1.6.6",
9+
"version": "1.6.7",
1010
"license": "MIT",
1111
"author": {
1212
"name": "Valentin Knabel",

src/Current.ts

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import { absolutePath } from "./AbsolutePath";
3131
import { existsSync } from "fs";
3232
import * as paths from "path";
3333
import * as glob from "glob";
34+
import * as os from "os";
3435

3536
export function prodEnvironment(): Current {
3637
return {
@@ -120,17 +121,23 @@ export function prodEnvironment(): Current {
120121
}
121122

122123
const fallbackGlobalSwiftFormatPath = (): string[] => {
123-
const defaultPath = ["/usr/bin/env", "swiftformat"];
124-
const path = vscode.workspace
124+
var path = vscode.workspace
125125
.getConfiguration()
126-
.get("swiftformat.path", defaultPath);
126+
.get<string[] | string | null>("swiftformat.path", null);
127+
127128
if (typeof path === "string") {
128-
return [absolutePath(path)];
129-
} else if (Array.isArray(path) && path.length > 0) {
130-
return [absolutePath(path[0]), ...path.slice(1)];
131-
} else {
132-
return defaultPath;
129+
return [path];
130+
}
131+
if (!Array.isArray(path) || path.length === 0) {
132+
path = [os.platform() === "win32" ? "swiftformat.exe" : "swiftformat"];
133133
}
134+
135+
if (os.platform() !== "win32" && !path[0].includes("/")) {
136+
// Only a binary name, not a path. Search for it in the path (on Windows this is implicit).
137+
path = ["/usr/bin/env", ...path];
138+
}
139+
140+
return path;
134141
};
135142

136143
const Current = prodEnvironment();

src/SwiftFormatEditProvider.ts

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,21 @@
11
import * as vscode from "vscode";
2-
import * as childProcess from "child_process";
32
import Current from "./Current";
43
import { handleFormatError } from "./UserInteraction";
54
import { existsSync } from "fs";
65
import { resolve } from "path";
6+
import { execShellSync } from "./execShell";
77

88
const wholeDocumentRange = new vscode.Range(
99
0,
1010
0,
1111
Number.MAX_SAFE_INTEGER,
12-
Number.MAX_SAFE_INTEGER
12+
Number.MAX_SAFE_INTEGER,
1313
);
1414

15-
function userDefinedFormatOptionsForDocument(
16-
document: vscode.TextDocument
17-
): { options: string[]; hasConfig: boolean } {
15+
function userDefinedFormatOptionsForDocument(document: vscode.TextDocument): {
16+
options: string[];
17+
hasConfig: boolean;
18+
} {
1819
const formatOptions = Current.config.formatOptions();
1920
if (formatOptions.indexOf("--config") != -1)
2021
return { options: formatOptions, hasConfig: true };
@@ -25,7 +26,7 @@ function userDefinedFormatOptionsForDocument(
2526
"./";
2627
const searchPaths = Current.config
2728
.formatConfigSearchPaths()
28-
.map(current => resolve(rootPath, current));
29+
.map((current) => resolve(rootPath, current));
2930
const existingConfig = searchPaths.find(existsSync);
3031
const options =
3132
existingConfig != null
@@ -48,7 +49,7 @@ function format(request: {
4849
const input = request.document.getText(request.range);
4950
if (input.trim() === "") return [];
5051
const userDefinedParams = userDefinedFormatOptionsForDocument(
51-
request.document
52+
request.document,
5253
);
5354
if (!userDefinedParams.hasConfig && Current.config.onlyEnableWithConfig()) {
5455
return [];
@@ -60,7 +61,7 @@ function format(request: {
6061
"--indent",
6162
request.formatting.insertSpaces
6263
? `${request.formatting.tabSize}`
63-
: "tabs"
64+
: "tabs",
6465
];
6566

6667
// Make the path explicitly absolute when on Windows. If we don't do this,
@@ -71,7 +72,7 @@ function format(request: {
7172
fileName = "/" + fileName;
7273
}
7374

74-
const newContents = childProcess.execFileSync(
75+
const newContents = execShellSync(
7576
swiftFormatPath[0],
7677
[
7778
...swiftFormatPath.slice(1),
@@ -80,19 +81,19 @@ function format(request: {
8081
fileName,
8182
...userDefinedParams.options,
8283
...(request.parameters || []),
83-
...formattingParameters
84+
...formattingParameters,
8485
],
8586
{
8687
encoding: "utf8",
87-
input
88-
}
88+
input,
89+
},
8990
);
9091
return newContents !== request.document.getText(request.range)
9192
? [
9293
vscode.TextEdit.replace(
9394
request.document.validateRange(request.range || wholeDocumentRange),
94-
newContents
95-
)
95+
newContents,
96+
),
9697
]
9798
: [];
9899
} catch (error) {
@@ -104,22 +105,23 @@ function format(request: {
104105
export class SwiftFormatEditProvider
105106
implements
106107
vscode.DocumentRangeFormattingEditProvider,
107-
vscode.DocumentFormattingEditProvider {
108+
vscode.DocumentFormattingEditProvider
109+
{
108110
provideDocumentRangeFormattingEdits(
109111
document: vscode.TextDocument,
110112
range: vscode.Range,
111-
formatting: vscode.FormattingOptions
113+
formatting: vscode.FormattingOptions,
112114
) {
113115
return format({
114116
document,
115117
parameters: ["--fragment", "true"],
116118
range,
117-
formatting
119+
formatting,
118120
});
119121
}
120122
provideDocumentFormattingEdits(
121123
document: vscode.TextDocument,
122-
formatting: vscode.FormattingOptions
124+
formatting: vscode.FormattingOptions,
123125
) {
124126
return format({ document, formatting });
125127
}

src/UserInteraction.ts

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,27 @@ import Current from "./Current";
44
enum FormatErrorInteraction {
55
configure = "Configure",
66
reset = "Reset",
7-
howTo = "How?"
7+
howTo = "How?",
88
}
99

1010
enum UnknownErrorInteraction {
11-
reportIssue = "Report issue"
11+
reportIssue = "Report issue",
1212
}
1313

1414
export async function handleFormatError(
1515
error: any,
16-
document: vscode.TextDocument
16+
document: vscode.TextDocument,
1717
) {
1818
function matches(...codeOrStatus: Array<number | string>) {
19-
return codeOrStatus.some(c => c === error.code || c === error.status);
19+
return codeOrStatus.some((c) => {
20+
if (typeof error.stderr === "string" && error.stderr.includes(c)) {
21+
return true;
22+
}
23+
return c === error.code || c === error.status;
24+
});
2025
}
21-
if (matches("ENOBUFS", "EPIPE")) {
26+
27+
if (matches("Domain=NSCocoaErrorDomain Code=260", "ENOBUFS", "EPIPE")) {
2228
return;
2329
} else if (matches("ENOENT", "EACCES", 127)) {
2430
const selection = await Current.editor.showErrorMessage(
@@ -27,7 +33,7 @@ export async function handleFormatError(
2733
?.join(" ")}.\nEnsure it is installed and in your PATH.`,
2834
FormatErrorInteraction.reset,
2935
FormatErrorInteraction.configure,
30-
FormatErrorInteraction.howTo
36+
FormatErrorInteraction.howTo,
3137
);
3238
switch (selection) {
3339
case FormatErrorInteraction.reset:
@@ -38,18 +44,18 @@ export async function handleFormatError(
3844
break;
3945
case FormatErrorInteraction.howTo:
4046
await Current.editor.openURL(
41-
"https://github.com/nicklockwood/SwiftFormat#command-line-tool"
47+
"https://github.com/nicklockwood/SwiftFormat#command-line-tool",
4248
);
4349
break;
4450
}
4551
} else if (matches(70)) {
4652
await Current.editor.showErrorMessage(
47-
`SwiftFormat failed. ${error.stderr || ""}`
53+
`SwiftFormat failed. ${error.stderr || ""}`,
4854
);
4955
} else {
5056
const unknownErrorSelection = await Current.editor.showErrorMessage(
5157
`An unknown error occurred. ${error.message || ""}`,
52-
UnknownErrorInteraction.reportIssue
58+
UnknownErrorInteraction.reportIssue,
5359
);
5460
if (unknownErrorSelection === UnknownErrorInteraction.reportIssue) {
5561
await Current.editor.reportIssueForError(error);

src/execShell.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import {
2+
execFileSync,
3+
ExecFileSyncOptionsWithStringEncoding,
4+
spawnSync,
5+
} from "child_process";
6+
import * as os from "os";
7+
8+
export function execShellSync(
9+
file: string,
10+
args: ReadonlyArray<string>,
11+
options: ExecFileSyncOptionsWithStringEncoding,
12+
): string {
13+
if (os.platform() === "win32") {
14+
const result = spawnSync(file, args ?? [], {
15+
...options,
16+
encoding: "utf8",
17+
shell: true,
18+
});
19+
if (result.error) {
20+
throw result.error;
21+
}
22+
return result.stdout;
23+
} else {
24+
return execFileSync(file, args, options);
25+
}
26+
}

src/extension.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,16 @@ export function activate(context: vscode.ExtensionContext) {
1515
buildSwiftformatIfNeeded().then(() => {
1616
const swiftSelector: vscode.DocumentSelector = {
1717
scheme: "file",
18-
language: "swift"
18+
language: "swift",
1919
};
2020
const editProvider = new SwiftFormatEditProvider();
2121
vscode.languages.registerDocumentRangeFormattingEditProvider(
2222
swiftSelector,
23-
editProvider
23+
editProvider,
2424
);
2525
vscode.languages.registerDocumentFormattingEditProvider(
2626
swiftSelector,
27-
editProvider
27+
editProvider,
2828
);
2929
});
3030
}
@@ -33,27 +33,27 @@ async function buildSwiftformatIfNeeded() {
3333
const manifests = await vscode.workspace.findFiles(
3434
"**/Package.swift",
3535
"**/.build/**",
36-
2
36+
2,
3737
);
3838
if (manifests.length == 0) {
3939
return;
4040
}
41-
const buildOperations = manifests.map(manifest => {
41+
const buildOperations = manifests.map((manifest) => {
4242
const manifestPath = manifest.fsPath;
4343
const manifestDir = path.dirname(manifestPath);
4444
return promisify(exec)("swift run -c release swiftformat --version", {
45-
cwd: manifestDir
45+
cwd: manifestDir,
4646
});
4747
});
4848
try {
4949
await vscode.window.withProgress(
5050
{
5151
location: vscode.ProgressLocation.Window,
52-
title: "Preparing swiftformat"
52+
title: "Preparing swiftformat",
5353
},
5454
async () => {
5555
await Promise.all(buildOperations);
56-
}
56+
},
5757
);
5858
} catch (error) {
5959
console.log(error);

0 commit comments

Comments
 (0)