mirror of https://github.com/webpack/webpack.git
add tool to format/sort code in files
This commit is contained in:
parent
66bd18c470
commit
beaded63c3
|
|
@ -0,0 +1,185 @@
|
|||
const path = require("path");
|
||||
const fs = require("fs");
|
||||
|
||||
// When --write is set, files will be written in place
|
||||
// Elsewise it only prints outdated files
|
||||
const doWrite = process.argv.includes("--write");
|
||||
|
||||
const allFiles = new Set();
|
||||
const findFiles = p => {
|
||||
const s = fs.statSync(p);
|
||||
if (s.isDirectory()) {
|
||||
for (const name of fs.readdirSync(p)) {
|
||||
if (name.startsWith(".")) continue;
|
||||
findFiles(path.join(p, name));
|
||||
}
|
||||
} else if (s.isFile()) {
|
||||
allFiles.add(p);
|
||||
}
|
||||
};
|
||||
findFiles(path.resolve(__dirname, "../lib"));
|
||||
|
||||
let canUpdateWithWrite = false;
|
||||
|
||||
const sortImport = (a, b) => {
|
||||
if (!a.key.startsWith(".") && b.key.startsWith(".")) return -1;
|
||||
if (a.key.startsWith(".") && !b.key.startsWith(".")) return 1;
|
||||
if (a.key < b.key) return -1;
|
||||
if (a.key > b.key) return 1;
|
||||
return 0;
|
||||
};
|
||||
|
||||
const execToArray = (content, regexp) => {
|
||||
const items = [];
|
||||
let match = regexp.exec(content);
|
||||
while (match) {
|
||||
items.push({
|
||||
content: match[0],
|
||||
key: match[1] + match[2]
|
||||
});
|
||||
match = regexp.exec(content);
|
||||
}
|
||||
return items;
|
||||
};
|
||||
|
||||
const schema = [
|
||||
{
|
||||
title: "license comment",
|
||||
regexp: /\/\*\n\s*MIT License http:\/\/www\.opensource\.org\/licenses\/mit-license\.php\n\s*(?:(Authors? .+)\n)?\s*\*\/\n/g,
|
||||
updateMessage: "update the license comment",
|
||||
update(content, author) {
|
||||
return (
|
||||
[
|
||||
"/*",
|
||||
"\tMIT License http://www.opensource.org/licenses/mit-license.php",
|
||||
author && `\t${author}`,
|
||||
"*/"
|
||||
]
|
||||
.filter(Boolean)
|
||||
.join("\n") + "\n"
|
||||
);
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "new line after license comment",
|
||||
regexp: /\n?/g,
|
||||
updateMessage: "insert a new line after the license comment",
|
||||
update() {
|
||||
return "\n";
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "strict mode",
|
||||
regexp: /"use strict";\n/g
|
||||
},
|
||||
{
|
||||
title: "new line after strict mode",
|
||||
regexp: /\n?/g,
|
||||
updateMessage: 'insert a new line after "use strict"',
|
||||
update() {
|
||||
return "\n";
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "imports",
|
||||
regexp: /(const (\{\s+\w+(,\s+\w+)*\s+\}|\w+) = require\("[^"]+"\)(\.\w+)*;\n)+\n/g,
|
||||
updateMessage: "sort imports alphabetically",
|
||||
update(content) {
|
||||
const items = execToArray(
|
||||
content,
|
||||
/const (?:\{\s+\w+(?:,\s+\w+)*\s+\}|\w+) = require\("([^"]+)"\)((?:\.\w+)*);\n/g
|
||||
);
|
||||
items.sort(sortImport);
|
||||
return items.map(item => item.content).join("") + "\n";
|
||||
},
|
||||
optional: true,
|
||||
repeat: true
|
||||
},
|
||||
{
|
||||
title: "type imports",
|
||||
regexp: /(\/\*\* @typedef \{import\("[^"]+"\)(\.\w+)*\} \w+ \*\/\n)+\n/g,
|
||||
updateMessage: "sort type imports alphabetically",
|
||||
update(content) {
|
||||
const items = execToArray(
|
||||
content,
|
||||
/\/\*\* @typedef \{import\("([^"]+)"\)((?:\.\w+)*)\} \w+ \*\/\n/g
|
||||
);
|
||||
items.sort(sortImport);
|
||||
return items.map(item => item.content).join("") + "\n";
|
||||
},
|
||||
optional: true,
|
||||
repeat: true
|
||||
}
|
||||
];
|
||||
|
||||
for (const filePath of allFiles) {
|
||||
let content = fs.readFileSync(filePath, "utf-8");
|
||||
const nl = /(\r?\n)/.exec(content);
|
||||
content = content.replace(/\r?\n/g, "\n");
|
||||
let newContent = content;
|
||||
|
||||
let state = 0;
|
||||
let pos = 0;
|
||||
// eslint-disable-next-line no-constant-condition
|
||||
while (true) {
|
||||
const current = schema[state];
|
||||
if (!current) break;
|
||||
current.regexp.lastIndex = pos;
|
||||
const match = current.regexp.exec(newContent);
|
||||
if (!match) {
|
||||
if (current.optional) {
|
||||
state++;
|
||||
continue;
|
||||
}
|
||||
console.log(`${filePath}: Missing ${current.title} at ${pos}`);
|
||||
process.exitCode = 1;
|
||||
break;
|
||||
}
|
||||
if (match.index !== pos) {
|
||||
console.log(
|
||||
`${filePath}: Unexpected code at ${pos}-${match.index}, expected ${
|
||||
current.title
|
||||
}`
|
||||
);
|
||||
process.exitCode = 1;
|
||||
pos = match.index;
|
||||
}
|
||||
if (!current.repeat) {
|
||||
state++;
|
||||
}
|
||||
if (current.update) {
|
||||
const update = current.update(...match);
|
||||
if (update !== match[0]) {
|
||||
newContent =
|
||||
newContent.substr(0, pos) +
|
||||
update +
|
||||
newContent.slice(pos + match[0].length);
|
||||
pos += update.length;
|
||||
if (!doWrite) {
|
||||
const updateMessage =
|
||||
current.updateMessage || `${current.title} need to be updated`;
|
||||
console.log(`${filePath}: ${updateMessage}`);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
pos += match[0].length;
|
||||
}
|
||||
|
||||
if (newContent !== content) {
|
||||
if (doWrite) {
|
||||
if (nl) {
|
||||
newContent = newContent.replace(/\n/g, nl[0]);
|
||||
}
|
||||
fs.writeFileSync(filePath, newContent, "utf-8");
|
||||
console.log(filePath);
|
||||
} else {
|
||||
canUpdateWithWrite = true;
|
||||
process.exitCode = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (canUpdateWithWrite) {
|
||||
console.log("Run 'yarn fix' to try to fix the problem automatically");
|
||||
}
|
||||
Loading…
Reference in New Issue