add more shapeshifter flags

This commit is contained in:
Felix Roos 2022-04-25 22:52:16 +02:00
parent d2ec9768f1
commit 0d325a3ec4

View File

@ -23,6 +23,8 @@ const isNote = (name) => /^[a-gC-G][bs]?[0-9]$/.test(name);
const addLocations = true; const addLocations = true;
export const addMiniLocations = true; export const addMiniLocations = true;
export const minifyStrings = true;
export const wrappedAsync = true;
export default (_code) => { export default (_code) => {
const { code, addReturn } = wrapAsync(_code); const { code, addReturn } = wrapAsync(_code);
@ -38,18 +40,18 @@ export default (_code) => {
} }
// replace template string `xxx` with mini(`xxx`) // replace template string `xxx` with mini(`xxx`)
if (isBackTickString(node)) { if (minifyStrings && isBackTickString(node)) {
return minifyWithLocation(node, node, ast.locations, artificialNodes); return minifyWithLocation(node, node, ast.locations, artificialNodes);
} }
// allows to use top level strings, which are normally directives... but we don't need directives // allows to use top level strings, which are normally directives... but we don't need directives
if (node.directives?.length === 1 && !node.statements?.length) { if (minifyStrings && node.directives?.length === 1 && !node.statements?.length) {
const str = new LiteralStringExpression({ value: node.directives[0].rawValue }); const str = new LiteralStringExpression({ value: node.directives[0].rawValue });
const wrapped = minifyWithLocation(str, node.directives[0], ast.locations, artificialNodes); const wrapped = minifyWithLocation(str, node.directives[0], ast.locations, artificialNodes);
return { ...node, directives: [], statements: [wrapped] }; return { ...node, directives: [], statements: [wrapped] };
} }
// replace double quote string "xxx" with mini('xxx') // replace double quote string "xxx" with mini('xxx')
if (isStringWithDoubleQuotes(node, ast.locations, code)) { if (minifyStrings && isStringWithDoubleQuotes(node, ast.locations, code)) {
return minifyWithLocation(node, node, ast.locations, artificialNodes); return minifyWithLocation(node, node, ast.locations, artificialNodes);
} }
@ -117,7 +119,9 @@ export default (_code) => {
}, },
}); });
// add return to last statement (because it's wrapped in an async function artificially) // add return to last statement (because it's wrapped in an async function artificially)
addReturn(shifted); if (wrappedAsync) {
addReturn(shifted);
}
const generated = codegen(shifted); const generated = codegen(shifted);
return generated; return generated;
}; };
@ -125,9 +129,11 @@ export default (_code) => {
function wrapAsync(code) { function wrapAsync(code) {
// wrap code in async to make await work on top level => this will create 1 line offset to locations // wrap code in async to make await work on top level => this will create 1 line offset to locations
// this is why line offset is -1 in getLocationObject calls below // this is why line offset is -1 in getLocationObject calls below
code = `(async () => { if (wrappedAsync) {
code = `(async () => {
${code} ${code}
})()`; })()`;
}
const addReturn = (ast) => { const addReturn = (ast) => {
const body = ast.statements[0].expression.callee.body; // actual code ast inside async function body const body = ast.statements[0].expression.callee.body; // actual code ast inside async function body
body.statements = body.statements body.statements = body.statements
@ -204,9 +210,10 @@ function hasModifierCall(parent) {
parent?.type === 'StaticMemberExpression' && Object.keys(Pattern.prototype.composable).includes(parent.property) parent?.type === 'StaticMemberExpression' && Object.keys(Pattern.prototype.composable).includes(parent.property)
); );
} }
const factories = Object.keys(Pattern.prototype.factories).concat(['mini']);
function isPatternFactory(node) { function isPatternFactory(node) {
return node?.type === 'CallExpression' && Object.keys(Pattern.prototype.factories).includes(node.callee.name); return node?.type === 'CallExpression' && factories.includes(node.callee.name);
} }
function canBeOverloaded(node) { function canBeOverloaded(node) {
@ -233,9 +240,14 @@ function reifyWithLocation(literalNode, node, locations, artificialNodes) {
// with this, the reified pattern can pass its location to the event, to know where to highlight when it's active // with this, the reified pattern can pass its location to the event, to know where to highlight when it's active
function minifyWithLocation(literalNode, node, locations, artificialNodes) { function minifyWithLocation(literalNode, node, locations, artificialNodes) {
const args = getLocationArguments(node, locations); const args = getLocationArguments(node, locations);
const wrapped = wrapFunction('mini', literalNode);
if (!addMiniLocations) {
artificialNodes.push(wrapped);
return wrapped;
}
const withLocation = new CallExpression({ const withLocation = new CallExpression({
callee: new StaticMemberExpression({ callee: new StaticMemberExpression({
object: wrapFunction('mini', literalNode), object: wrapped,
property: 'withMiniLocation', property: 'withMiniLocation',
}), }),
arguments: args, arguments: args,
@ -246,17 +258,18 @@ function minifyWithLocation(literalNode, node, locations, artificialNodes) {
function getLocationArguments(node, locations) { function getLocationArguments(node, locations) {
const loc = locations.get(node); const loc = locations.get(node);
const lineOffset = wrappedAsync ? -1 : 0;
return [ return [
new ArrayExpression({ new ArrayExpression({
elements: [ elements: [
new LiteralNumericExpression({ value: loc.start.line - 1 }), // the minus 1 assumes the code has been wrapped in async iife new LiteralNumericExpression({ value: loc.start.line + lineOffset }), // the minus 1 assumes the code has been wrapped in async iife
new LiteralNumericExpression({ value: loc.start.column }), new LiteralNumericExpression({ value: loc.start.column }),
new LiteralNumericExpression({ value: loc.start.offset }), new LiteralNumericExpression({ value: loc.start.offset }),
], ],
}), }),
new ArrayExpression({ new ArrayExpression({
elements: [ elements: [
new LiteralNumericExpression({ value: loc.end.line - 1 }), // the minus 1 assumes the code has been wrapped in async iife new LiteralNumericExpression({ value: loc.end.line + lineOffset }), // the minus 1 assumes the code has been wrapped in async iife
new LiteralNumericExpression({ value: loc.end.column }), new LiteralNumericExpression({ value: loc.end.column }),
new LiteralNumericExpression({ value: loc.end.offset }), new LiteralNumericExpression({ value: loc.end.offset }),
], ],