Skip to content

Commit 6256ebc

Browse files
cortinicofacebook-github-bot
authored andcommitted
Check all C-family sources with clang-format
Summary: Add npm-driven clang-format commands for exported C-family sources. Expose `yarn format-cpp` and `yarn format-check-cpp`, and compose them into the repository-wide commands. The wrapper automatically selects the repository-provided formatter for its environment. Changelog: [Internal] Differential Revision: D119487611
1 parent 83f6a4c commit 6256ebc

3 files changed

Lines changed: 65 additions & 13 deletions

File tree

.clang-format-ignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
**/Pods/**
2+
**/build/**
3+
**/node_modules/**
14
packages/react-native/React/I18n/FBXXHashUtils.h
25
packages/react-native/ReactAndroid/src/main/jni/first-party/yogajni/**
36
packages/react-native/ReactAndroid/src/main/jni/third-party/**

package.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,16 @@
99
"build-android": "./gradlew :packages:react-native:ReactAndroid:build",
1010
"build": "node ./scripts/build/build.js",
1111
"build-types": "node ./scripts/js-api/build-types",
12-
"clang-format": "node ./scripts/clang-format.js",
1312
"clean": "node ./scripts/build/clean.js",
1413
"cxx-api-build": "python -m scripts.cxx-api.parser",
1514
"cxx-api-validate": "python -m scripts.cxx-api.parser --validate",
1615
"flow-check": "flow full-check",
1716
"flow": "flow",
18-
"format-check": "yarn format-check-javascript",
17+
"format-check": "yarn format-check-javascript && yarn format-check-cpp",
18+
"format-check-cpp": "node ./scripts/clang-format.js --check",
1919
"format-check-javascript": "prettier --check \"./**/*.{cjs,cts,flow,js,jsx,md,mjs,mts,ts,tsx,yaml,yml}\"",
20-
"format": "yarn format-javascript && yarn clang-format",
20+
"format": "yarn format-javascript && yarn format-cpp",
21+
"format-cpp": "node ./scripts/clang-format.js",
2122
"format-javascript": "prettier --write \"./**/*.{cjs,cts,flow,js,jsx,md,mjs,mts,ts,tsx,yaml,yml}\"",
2223
"featureflags": "yarn --cwd packages/react-native featureflags",
2324
"js-api-diff": "node ./scripts/js-api/diff-api-snapshot",

scripts/clang-format.js

Lines changed: 58 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,49 @@
1010

1111
'use strict';
1212

13-
const dotslash = require('fb-dotslash');
1413
const {spawnSync} = require('node:child_process');
1514
const fs = require('node:fs');
1615
const path = require('node:path');
1716
const {globSync} = require('tinyglobby');
1817

1918
const REPO_ROOT = path.resolve(__dirname, '..');
20-
const CLANG_FORMAT = path.join(__dirname, 'clang-format');
19+
const OSS_CLANG_FORMAT_DOTSLASH = path.join(__dirname, 'clang-format');
2120
const GENERATED_MARKER = Buffer.from('@' + 'generated');
21+
const IGNORE_FILE = path.join(REPO_ROOT, '.clang-format-ignore');
2222
const MAX_HEADER_BYTES = 4096;
2323
const MAX_FILES_PER_PROCESS = 30;
2424

25+
const SOURCE_GLOB = '**/*.{c,cc,cpp,cu,cuh,cxx,h,hh,hpp,hxx,m,mm,proto,tcc}';
26+
27+
function findClangFormat() {
28+
if (process.env.CLANG_FORMAT != null && process.env.CLANG_FORMAT !== '') {
29+
return {command: process.env.CLANG_FORMAT, prefixArguments: []};
30+
}
31+
32+
try {
33+
const metaClangFormat = require('./clang-format.fb').findMetaClangFormat();
34+
if (metaClangFormat != null) {
35+
return metaClangFormat;
36+
}
37+
} catch (error) {
38+
if (
39+
error == null ||
40+
error.code !== 'MODULE_NOT_FOUND' ||
41+
!String(error.message).includes("'./clang-format.fb'")
42+
) {
43+
throw error;
44+
}
45+
}
46+
47+
return {
48+
command:
49+
process.env.DOTSLASH != null && process.env.DOTSLASH !== ''
50+
? process.env.DOTSLASH
51+
: require('fb-dotslash'),
52+
prefixArguments: [OSS_CLANG_FORMAT_DOTSLASH],
53+
};
54+
}
55+
2556
/** @param {string} file */
2657
function isGenerated(file) {
2758
let fd;
@@ -41,16 +72,33 @@ function isGenerated(file) {
4172
}
4273

4374
function main() {
75+
const arguments_ = process.argv.slice(2);
76+
const check = arguments_.includes('--check');
77+
const clangFormat = findClangFormat();
78+
const positionalArguments = arguments_.filter(
79+
argument => argument !== '--check',
80+
);
81+
const ignore = fs
82+
.readFileSync(IGNORE_FILE, 'utf8')
83+
.split('\n')
84+
.map(line => line.trim())
85+
.filter(line => line !== '' && !line.startsWith('#'));
86+
const discoveredFiles = globSync(SOURCE_GLOB, {cwd: REPO_ROOT, ignore});
4487
const files =
45-
process.argv.length > 2
46-
? process.argv.slice(2)
47-
: globSync('*/**/*.{h,cpp,m,mm}', {cwd: REPO_ROOT});
88+
positionalArguments.length > 0
89+
? positionalArguments.filter(file => discoveredFiles.includes(file))
90+
: discoveredFiles;
4891
const sourceFiles = files.filter(file => !isGenerated(file));
92+
let exitStatus = 0;
4993

5094
for (let i = 0; i < sourceFiles.length; i += MAX_FILES_PER_PROCESS) {
95+
const formatterArguments = [
96+
...(check ? ['--dry-run', '--Werror'] : ['-i']),
97+
...sourceFiles.slice(i, i + MAX_FILES_PER_PROCESS),
98+
];
5199
const result = spawnSync(
52-
dotslash,
53-
[CLANG_FORMAT, '-i', ...sourceFiles.slice(i, i + MAX_FILES_PER_PROCESS)],
100+
clangFormat.command,
101+
[...clangFormat.prefixArguments, ...formatterArguments],
54102
{
55103
cwd: REPO_ROOT,
56104
stdio: 'inherit',
@@ -61,13 +109,13 @@ function main() {
61109
throw result.error;
62110
}
63111
if (result.signal != null) {
64-
process.kill(process.pid, result.signal);
65-
return;
112+
throw new Error(`clang-format was terminated by ${result.signal}`);
66113
}
67114
if (result.status !== 0) {
68-
process.exit(result.status ?? 1);
115+
exitStatus = result.status ?? 1;
69116
}
70117
}
118+
process.exitCode = exitStatus;
71119
}
72120

73121
main();

0 commit comments

Comments
 (0)