Files
react-native/scripts/format-kotlin.js
T
Nicola Corti 07e4bf34d0 Add Kotlin to yarn format (#58462)
Summary:
Pull Request resolved: https://github.com/react/react-native/pull/58462

Add `yarn format-kotlin` and `yarn format-check-kotlin` using the npm `ktfmt` package and its bundled formatter jar. This adds the offline package mirror and workspace lock entry without changing existing Kotlin source formatting or Gradle configuration. The wrapper discovers a suitable JDK when available and otherwise prints environment-specific Java 17 setup guidance before skipping Kotlin.

allow-large-files: The npm package intentionally contains the upstream ktfmt executable jar so offline and public installs use the same formatter.

Changelog: [Internal]

Reviewed By: javache

Differential Revision: D119487612

fbshipit-source-id: cb699a1286cffbf461ef69ed66f694e3f69415d0
2026-09-15 11:23:27 -07:00

82 lines
2.1 KiB
JavaScript

/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @noflow
* @format
*/
'use strict';
const {findJava, warnMissingJava} = require('./format-utils');
const {spawnSync} = require('node:child_process');
const fs = require('node:fs');
const path = require('node:path');
const {globSync} = require('tinyglobby');
const REPO_ROOT = path.resolve(__dirname, '..');
const KTFMT_JAR = require.resolve('ktfmt/lib/ktfmt.jar');
const GENERATED_MARKER = Buffer.from('@' + 'generated');
const MINIMUM_JAVA_VERSION = 17;
const MAX_FILES_PER_PROCESS = 100;
const MAX_HEADER_BYTES = 4096;
const IGNORE = [
'**/build/**',
'**/com/facebook/yoga/**',
'**/hermes-engine/**',
'**/internal/featureflags/**',
'**/node_modules/**',
'**/systeminfo/ReactNativeVersion.kt',
];
function isGenerated(file) {
const fd = fs.openSync(path.resolve(REPO_ROOT, file), 'r');
try {
const header = Buffer.alloc(MAX_HEADER_BYTES);
const bytesRead = fs.readSync(fd, header, 0, header.length, 0);
return header.subarray(0, bytesRead).includes(GENERATED_MARKER);
} finally {
fs.closeSync(fd);
}
}
function main() {
const check = process.argv[2] === '--check';
const java = findJava(MINIMUM_JAVA_VERSION);
if (java == null) {
warnMissingJava('Kotlin');
return;
}
const files = globSync('**/*.{kt,kts}', {
cwd: REPO_ROOT,
ignore: IGNORE,
}).filter(file => !isGenerated(file));
for (let i = 0; i < files.length; i += MAX_FILES_PER_PROCESS) {
const result = spawnSync(
java,
[
'-jar',
KTFMT_JAR,
'--do-not-remove-unused-imports',
...(check ? ['--dry-run', '--set-exit-if-changed'] : []),
...files.slice(i, i + MAX_FILES_PER_PROCESS),
],
{cwd: REPO_ROOT, stdio: 'inherit'},
);
if (result.error != null) {
throw result.error;
}
if (result.signal != null) {
process.kill(process.pid, result.signal);
return;
}
if (result.status !== 0) {
process.exit(result.status ?? 1);
}
}
}
main();