chore: Add a lint step for field name constants (#32769)
We have a small linter NodeJS script that checks if any field name constants are defined incorrectly. This PR adds this linter to the build script, so it'll be run in CI.
This commit is contained in:
parent
7a50b9095f
commit
97e3791d3a
|
|
@ -34,6 +34,7 @@ if [[ -f .env ]]; then
|
||||||
source .env
|
source .env
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
node scripts/check-field-constants.mjs
|
||||||
|
|
||||||
# Build the code. $@ accepts all the parameters from the input command line and uses it in the maven build command
|
# Build the code. $@ accepts all the parameters from the input command line and uses it in the maven build command
|
||||||
mvn clean package "$@"
|
mvn clean package "$@"
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,13 @@
|
||||||
|
/**
|
||||||
|
* This script checks if the field constants in the Java files are named and defined correctly.
|
||||||
|
*/
|
||||||
|
|
||||||
import {promises as fs} from "fs";
|
import {promises as fs} from "fs";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
|
|
||||||
async function findInnerClassDefinitions(directory) {
|
async function findInnerClassDefinitions(directory) {
|
||||||
|
let isPass = true;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const files = await fs.readdir(directory);
|
const files = await fs.readdir(directory);
|
||||||
|
|
||||||
|
|
@ -10,29 +16,37 @@ async function findInnerClassDefinitions(directory) {
|
||||||
const stats = await fs.stat(filePath);
|
const stats = await fs.stat(filePath);
|
||||||
|
|
||||||
if (stats.isDirectory()) {
|
if (stats.isDirectory()) {
|
||||||
await findInnerClassDefinitions(filePath);
|
if (!await findInnerClassDefinitions(filePath)) {
|
||||||
} else if (path.extname(filePath) === '.java') {
|
isPass = false;
|
||||||
await processJavaFile(filePath);
|
}
|
||||||
|
} else if (path.extname(filePath) === ".java") {
|
||||||
|
if (!await processJavaFile(filePath)) {
|
||||||
|
isPass = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
|
isPass = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return isPass;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function processJavaFile(filePath) {
|
async function processJavaFile(filePath) {
|
||||||
|
let isPass = true;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const contents = await fs.readFile(filePath, 'utf8');
|
const contents = await fs.readFile(filePath, "utf8");
|
||||||
|
|
||||||
const innerClassRegex = /^ {4}([\w ]+?)\s+class\s+Fields\s+(extends (\w+)\.Fields)?\s*{(.+?\n {4})?}$/gsm;
|
const innerClassRegex = /^ {4}([\w ]+?)\s+class\s+Fields\s+(extends (\w+)\.Fields)?\s*{(.+?\n {4})?}$/gsm;
|
||||||
|
|
||||||
for (const innerClassMatch of contents.matchAll(innerClassRegex)) {
|
for (const innerClassMatch of contents.matchAll(innerClassRegex)) {
|
||||||
const classQualifiers = innerClassMatch[1]; // we don't care much about this
|
const classQualifiers = innerClassMatch[1]; // we don't care much about this
|
||||||
const expectedParentClass = innerClassMatch[3];
|
const expectedParentClass = innerClassMatch[3];
|
||||||
console.log(filePath, classQualifiers, expectedParentClass);
|
|
||||||
|
|
||||||
for (const match of innerClassMatch[0].matchAll(/\bpublic\s+static\s+final\s+String\s+(\w+)\s+=\s+(.+?);/gs)) {
|
for (const match of innerClassMatch[0].matchAll(/\bpublic\s+static\s+final\s+String\s+(\w+)\s+=\s+(.+?);/gs)) {
|
||||||
const key = match[1]
|
const key = match[1];
|
||||||
const valMatcherParts = [`^dotted\\(`];
|
const valMatcherParts = [`^dotted\\(`];
|
||||||
for (const [i, field] of key.split("_").entries()) {
|
for (const [i, field] of key.split("_").entries()) {
|
||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
|
|
@ -41,12 +55,14 @@ async function processJavaFile(filePath) {
|
||||||
valMatcherParts.push(`(\\w+\\.\\w+\\.)?${field}`);
|
valMatcherParts.push(`(\\w+\\.\\w+\\.)?${field}`);
|
||||||
}
|
}
|
||||||
valMatcherParts.push(`\\s*\\)$`);
|
valMatcherParts.push(`\\s*\\)$`);
|
||||||
const valMatcher = new RegExp(valMatcherParts.join(''));
|
const valMatcher = new RegExp(valMatcherParts.join(""));
|
||||||
if (!valMatcher.test(match[2])) {
|
if (!valMatcher.test(match[2])) {
|
||||||
console.log("key is", key);
|
console.log(filePath, classQualifiers, expectedParentClass);
|
||||||
console.log("val is", match[2]);
|
console.log("\tkey is", key);
|
||||||
console.log("pattern", valMatcher);
|
console.log("\tval is", match[2]);
|
||||||
console.error(`Field ${key} in ${filePath} is not looking right.`);
|
console.log("\tpattern", valMatcher);
|
||||||
|
console.error(`\tField ${key} in ${filePath} is not looking right.`);
|
||||||
|
isPass = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -58,8 +74,23 @@ async function processJavaFile(filePath) {
|
||||||
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
}
|
isPass = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const directoryPath = '.';
|
return isPass;
|
||||||
findInnerClassDefinitions(directoryPath);
|
}
|
||||||
|
|
||||||
|
// Can't use `import.meta.dirname` because it's not available in Node.js 18.
|
||||||
|
// And v18 is what is included in GitHub Actions today.
|
||||||
|
// See <https://github.com/actions/runner-images/blob/main/images/ubuntu/Ubuntu2204-Readme.md#language-and-runtime>.
|
||||||
|
const directoryPath = import.meta.resolve("..").replace("file://", "");
|
||||||
|
|
||||||
|
findInnerClassDefinitions(directoryPath)
|
||||||
|
.then(isPass => {
|
||||||
|
if (isPass) {
|
||||||
|
console.log("All okay.");
|
||||||
|
} else {
|
||||||
|
console.error("Some field constants are not looking good.");
|
||||||
|
process.exitCode = 1;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user