Skip to content

Commit ede7ebf

Browse files
authored
Fix Swift formatter detection when version is main
## Summary: Fixes #59598. Some Swift toolchains report `main` for `swift format --version`, so the formatter is skipped even when the toolchain meets the minimum version. When `swift format` reports `main`, check `swift --version` and use it to enforce the existing minimum version. Other formatter candidates still require a parseable formatter version. ## Changelog: [INTERNAL] [FIXED] - Detect the Swift toolchain version when `swift format` reports `main`. ## Test Plan: - Ran `NODE_PATH=/Volumes/SSD512/Work/mobile/force-mobile/node_modules /Volumes/SSD512/Work/mobile/force-mobile/node_modules/.bin/jest scripts/__tests__/format-swift-test.js --runInBand --config '{"rootDir":"/tmp/react-native-contribution","testEnvironment":"node","transform":{}}'`: 2 tests passed. The Swift 6.4 case failed before the change; the Swift 6.2 case remains rejected. - Ran `git diff --check`: passed. - Xcode 27.1 was not available for an end-to-end check. The test simulates its reported version output. Full repository checks were not run. Differential Revision: D128394284 Pull Request resolved: #59623
1 parent a5e2042 commit ede7ebf

2 files changed

Lines changed: 77 additions & 1 deletion

File tree

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/**
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*
7+
* @noflow
8+
* @format
9+
*/
10+
11+
'use strict';
12+
13+
jest.mock('../format-utils', () => ({
14+
IS_META_CHECKOUT: false,
15+
commandVersion: jest.fn(),
16+
findMetaTool: jest.fn(() => null),
17+
}));
18+
jest.mock('tinyglobby', () => ({globSync: jest.fn(() => [])}));
19+
20+
const originalSwiftFormat = process.env.SWIFT_FORMAT;
21+
22+
beforeEach(() => {
23+
delete process.env.SWIFT_FORMAT;
24+
});
25+
26+
afterEach(() => {
27+
if (originalSwiftFormat === undefined) {
28+
delete process.env.SWIFT_FORMAT;
29+
} else {
30+
process.env.SWIFT_FORMAT = originalSwiftFormat;
31+
}
32+
jest.resetModules();
33+
jest.clearAllMocks();
34+
jest.restoreAllMocks();
35+
});
36+
37+
test.each([
38+
['6.4', true],
39+
['6.2', false],
40+
])(
41+
'checks the Swift toolchain version when the formatter reports main (%s)',
42+
(version, accepted) => {
43+
const {commandVersion} = require('../format-utils');
44+
const {globSync} = require('tinyglobby');
45+
commandVersion.mockImplementation((command, args) => {
46+
if (command === 'swift' && args?.[0] === 'format') {
47+
return {status: 0, output: 'main'};
48+
}
49+
if (command === 'swift') {
50+
return {
51+
status: 0,
52+
output: `Apple Swift version ${version} (swiftlang)`,
53+
};
54+
}
55+
return {status: 1, output: ''};
56+
});
57+
jest.spyOn(console, 'warn').mockImplementation(() => {});
58+
59+
require('../format-swift');
60+
61+
expect(globSync).toHaveBeenCalledTimes(accepted ? 1 : 0);
62+
},
63+
);

‎scripts/format-swift.js‎

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,20 @@ function findSwiftFormat() {
8181
}
8282
for (const [command, prefixArguments] of candidates) {
8383
const result = commandVersion(command, prefixArguments);
84-
const version = parseSwiftFormatVersion(result.output);
84+
let version = parseSwiftFormatVersion(result.output);
85+
if (
86+
result.status === 0 &&
87+
version == null &&
88+
result.output.trim() === 'main' &&
89+
command === 'swift' &&
90+
prefixArguments.length === 1 &&
91+
prefixArguments[0] === 'format'
92+
) {
93+
const toolchain = commandVersion(command);
94+
if (toolchain.status === 0) {
95+
version = parseSwiftFormatVersion(toolchain.output);
96+
}
97+
}
8598
if (
8699
result.status === 0 &&
87100
version != null &&

0 commit comments

Comments
 (0)