Created
September 2, 2019 09:09
-
-
Save voldern/7a37bc9414da1b6913ea2bf500364d8f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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