Skip to content

Instantly share code, notes, and snippets.

@voldern
Created September 2, 2019 09:09
Show Gist options
  • Save voldern/7a37bc9414da1b6913ea2bf500364d8f to your computer and use it in GitHub Desktop.
Save voldern/7a37bc9414da1b6913ea2bf500364d8f to your computer and use it in GitHub Desktop.
const util = require("util");
const fs = require("fs");
const path = require("path");
const acorn = require("acorn");
const astCompare = require("ast-compare");
const { without, replace, equals } = require("ramda");
const otherDir = process.argv[2];
const file = process.argv[3];
if (!otherDir || !file) {
console.error("Failed: Missing params");
process.exit(1);
}
const MyParser = acorn.Parser.extend(
require("acorn-jsx")(),
require("acorn-static-class-features"),
require("acorn-class-fields")
);
const otherFile = path.join(...[otherDir, ...file.split("/").slice(2)]);
const content = fs.readFileSync(file);
const contentOther = fs.readFileSync(otherFile);
const ast = MyParser.parse(content, { ecmaVersion: 11, sourceType: "module" });
const astOther = MyParser.parse(contentOther, {
ecmaVersion: 11,
sourceType: "module"
});
const filterEmptyJSXText = node => {
if (node.type === "JSXText") {
return node.value.trim() != "";
}
if (
node.type === "JSXExpressionContainer" &&
node.expression.type === "Literal"
) {
return node.expression.value.trim() !== "";
}
return true;
};
const removeWhitespace = replace(/[ \n]/g, "");
function walkTree(ast, ast2, nodeType) {
//console.log('Test1', ast, ast2);
if (ast instanceof acorn.Node) {
if (ast.type !== ast2.type) {
// We want to support going from Literal to Identifier as key in objects.
// For example:
// { key: '' }
// to
// { 'key': '' }
if (
((ast.type === "Literal" && ast2.type === "Identifier") ||
(ast.type === "Identifier" && ast2.type === "Literal")) &&
ast.name === ast2.value
) {
return;
}
throw new Error(`${ast} does not match ${ast2}`);
}
const keys = without(["start", "end", "bigint"], Object.keys(ast));
return keys.forEach(key => walkTree(ast[key], ast2[key], ast.type));
}
if (Array.isArray(ast)) {
// We can live without EmptyStatements and superflous JSX text
ast = ast.filter(
node => node.type !== "EmptyStatement" && filterEmptyJSXText(node)
);
ast2 = ast2.filter(
node => node.type !== "EmptyStatement" && filterEmptyJSXText(node)
);
if (ast.length !== ast2.length) {
throw new Error(`${ast} length does not match ${ast2}`);
}
return ast.forEach((node, index) => walkTree(node, ast2[index], nodeType));
}
if (!equals(ast, ast2)) {
// JSX allows whitespace to move around
if (
nodeType === "JSXText" &&
removeWhitespace(ast) === removeWhitespace(ast2)
) {
return;
}
// We want to support removal of whitespace
if (ast.trim() === ast2.trim()) {
return;
}
// We want to support going from `"` to `'` quotes
if (ast === ast2.replace(/"/g, "'")) {
return;
}
throw new Error(`${ast} does not match ${ast2}`);
}
}
try {
walkTree(ast, astOther);
} catch (err) {
console.log(`File1: ${file}. File 2 ${otherFile}`);
throw err;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment