mirror of
https://github.com/facebook/react-native.git
synced 2024-11-21 12:39:27 +00:00
d6e0bc714a
Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41334 TSIA. Changelog: [Internal] Reviewed By: robhogan Differential Revision: D51025812 fbshipit-source-id: e10d437be775a6b80946483aa96460f34927f870
206 lines
5.0 KiB
JavaScript
206 lines
5.0 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.
|
|
*
|
|
* @format
|
|
*/
|
|
|
|
'use strict';
|
|
|
|
const fs = require('fs');
|
|
const https = require('https');
|
|
const os = require('os');
|
|
const path = require('path');
|
|
const {exec} = require('shelljs');
|
|
const yargs = require('yargs');
|
|
|
|
const googleJavaFormatUrl =
|
|
'https://github.com/google/google-java-format/releases/download/google-java-format-1.7/google-java-format-1.7-all-deps.jar';
|
|
const googleJavaFormatPath = path.join(
|
|
os.tmpdir(),
|
|
'google-java-format-all-deps.jar',
|
|
);
|
|
const javaFilesCommand = 'find ./ReactAndroid -name "*.java"';
|
|
|
|
function _download(url, downloadPath, resolve, reject, redirectCount) {
|
|
https.get(url, response => {
|
|
switch (response.statusCode) {
|
|
case 302: //Permanent Redirect
|
|
if (redirectCount === 0) {
|
|
throw new Error(
|
|
`Unhandled response code (HTTP${response.statusCode}) while retrieving google-java-format binary from ${url}`,
|
|
);
|
|
}
|
|
|
|
_download(
|
|
response.headers.location,
|
|
downloadPath,
|
|
resolve,
|
|
reject,
|
|
redirectCount - 1,
|
|
);
|
|
break;
|
|
case 200: //OK
|
|
const file = fs.createWriteStream(downloadPath);
|
|
|
|
response.pipe(file);
|
|
file.on('finish', () => file.close(() => resolve()));
|
|
break;
|
|
default:
|
|
reject(
|
|
`Unhandled response code (HTTP${response.statusCode}) while retrieving google-java-format binary from ${url}`,
|
|
);
|
|
}
|
|
});
|
|
}
|
|
|
|
function download(url, downloadPath) {
|
|
return new Promise((resolve, reject) => {
|
|
_download(url, downloadPath, resolve, reject, 1);
|
|
});
|
|
}
|
|
|
|
function filesWithLintingIssues() {
|
|
const proc = exec(
|
|
`java -jar ${googleJavaFormatPath} --dry-run $(${javaFilesCommand})`,
|
|
{silent: true},
|
|
);
|
|
|
|
if (proc.code !== 0) {
|
|
throw new Error(proc.stderr);
|
|
}
|
|
|
|
return proc.stdout.split('\n').filter(x => x);
|
|
}
|
|
|
|
function unifiedDiff(file) {
|
|
const lintedProc = exec(
|
|
`java -jar ${googleJavaFormatPath} --set-exit-if-changed ${file}`,
|
|
{silent: true},
|
|
);
|
|
|
|
//Exit code 1 indicates lint violations, which is what we're expecting
|
|
if (lintedProc.code !== 1) {
|
|
throw new Error(lintedProc.stderr);
|
|
}
|
|
|
|
const diffProc = lintedProc.exec(`diff -U 0 ${file} -`, {silent: true});
|
|
|
|
//Exit code 0 if inputs are the same, 1 if different, 2 if trouble.
|
|
if (diffProc.code !== 0 && diffProc.code !== 1) {
|
|
throw new Error(diffProc.stderr);
|
|
}
|
|
|
|
return {
|
|
file,
|
|
diff: diffProc.stdout,
|
|
};
|
|
}
|
|
|
|
function extractRangeInformation(range) {
|
|
//eg;
|
|
// @@ -54 +54,2 @@
|
|
// @@ -1,3 +1,9 @@
|
|
|
|
const regex = /^@@ [-+](\d+,?\d+) [-+](\d+,?\d+) @@$/;
|
|
const match = regex.exec(range);
|
|
|
|
if (match) {
|
|
const original = match[1].split(',');
|
|
const updated = match[2].split(',');
|
|
|
|
return {
|
|
original: {
|
|
line: parseInt(original[0], 10),
|
|
lineCount: parseInt(original[1], 10) || 1,
|
|
},
|
|
updated: {
|
|
line: parseInt(updated[0], 10),
|
|
lineCount: parseInt(updated[1], 10) || 1,
|
|
},
|
|
};
|
|
}
|
|
}
|
|
|
|
function parseChanges(file, diff) {
|
|
let group = null;
|
|
const groups = [];
|
|
|
|
diff.split('\n').forEach(line => {
|
|
const range = extractRangeInformation(line);
|
|
|
|
if (range) {
|
|
group = {
|
|
range,
|
|
description: [line],
|
|
};
|
|
groups.push(group);
|
|
} else if (group) {
|
|
group.description.push(line);
|
|
}
|
|
});
|
|
|
|
return groups.map(x => ({
|
|
file,
|
|
line: x.range.original.line,
|
|
lineCount: x.range.original.lineCount,
|
|
description: x.description.join('\n'),
|
|
}));
|
|
}
|
|
|
|
async function main() {
|
|
const {argv} = yargs
|
|
.scriptName('lint-java')
|
|
.usage('Usage: $0 [options]')
|
|
.command(
|
|
'$0',
|
|
'Downloads the google-java-format package and reformats Java source code to comply with Google Java Style.\n\nSee https://github.com/google/google-java-format',
|
|
)
|
|
.option('check', {
|
|
type: 'boolean',
|
|
description:
|
|
'Outputs a list of files with lint violations.\nExit code is set to 1 if there are violations, otherwise 0.\nDoes not reformat lint issues.',
|
|
})
|
|
.option('diff', {
|
|
type: 'boolean',
|
|
description:
|
|
'Outputs a diff of the lint fix changes in json format.\nDoes not reformat lint issues.',
|
|
});
|
|
|
|
await download(googleJavaFormatUrl, googleJavaFormatPath);
|
|
|
|
if (argv.check) {
|
|
const files = filesWithLintingIssues();
|
|
|
|
files.forEach(x => console.log(x));
|
|
|
|
process.exit(files.length === 0 ? 0 : 1);
|
|
|
|
return;
|
|
}
|
|
|
|
if (argv.diff) {
|
|
const suggestions = filesWithLintingIssues()
|
|
.map(unifiedDiff)
|
|
.filter(x => x)
|
|
.map(x => parseChanges(x.file, x.diff))
|
|
.reduce((accumulator, current) => accumulator.concat(current), []);
|
|
|
|
console.log(JSON.stringify(suggestions));
|
|
|
|
return;
|
|
}
|
|
|
|
const proc = exec(
|
|
`java -jar ${googleJavaFormatPath} --set-exit-if-changed --replace $(${javaFilesCommand})`,
|
|
);
|
|
|
|
process.exit(proc.code);
|
|
}
|
|
|
|
(async () => {
|
|
await main();
|
|
})();
|