-
Notifications
You must be signed in to change notification settings - Fork 135
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix second half of type errors. Only macro errors remaining
- Loading branch information
1 parent
7bad187
commit 121785b
Showing
12 changed files
with
247 additions
and
126 deletions.
There are no files selected for viewing
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
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,6 @@ | ||
// const printAST = require('ast-pretty-print') | ||
const {createMacro} = require('../../') | ||
import {createMacro} from '../../' | ||
|
||
module.exports = createMacro(evalMacro) | ||
|
||
function evalMacro() { | ||
module.exports = createMacro(function evalMacro() { | ||
throw new Error('very unhelpful') | ||
} | ||
}) |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,54 +1,106 @@ | ||
const {parse} = require('@babel/parser') | ||
import {parse} from '@babel/parser' | ||
import {Node, NodePath} from '@babel/traverse' | ||
import {Expression, Statement, VariableDeclaration} from '@babel/types' | ||
// const printAST = require('ast-pretty-print') | ||
const {createMacro} = require('../../') | ||
import {createMacro} from '../../' | ||
|
||
module.exports = createMacro(evalMacro) | ||
|
||
function evalMacro({references, state}) { | ||
export default createMacro(function evalMacro({references, state}) { | ||
references.default.forEach(referencePath => { | ||
if (referencePath.parentPath.type === 'TaggedTemplateExpression') { | ||
asTag(referencePath.parentPath.get('quasi'), state) | ||
} else if (referencePath.parentPath.type === 'CallExpression') { | ||
asFunction(referencePath.parentPath.get('arguments'), state) | ||
} else if (referencePath.parentPath.type === 'JSXOpeningElement') { | ||
asJSX( | ||
{ | ||
attributes: referencePath.parentPath.get('attributes'), | ||
children: referencePath.parentPath.parentPath.get('children'), | ||
}, | ||
state, | ||
) | ||
if (referencePath.parentPath?.type === 'TaggedTemplateExpression') { | ||
asTag(referencePath.parentPath?.get('quasi')) | ||
} else if (referencePath.parentPath?.type === 'CallExpression') { | ||
const args = referencePath.parentPath?.get('arguments') | ||
if (!Array.isArray(args)) { | ||
throw new Error('Was expecting array') | ||
} | ||
asFunction(args) | ||
} else if (referencePath.parentPath?.type === 'JSXOpeningElement') { | ||
asJSX({ | ||
attributes: referencePath.parentPath?.get('attributes'), | ||
children: referencePath.parentPath?.parentPath?.get('children'), | ||
}) | ||
} else { | ||
// TODO: throw a helpful error message | ||
} | ||
}) | ||
} | ||
}) | ||
|
||
function asTag(quasiPath: NodePath | NodePath[]) { | ||
if (Array.isArray(quasiPath)) { | ||
throw new Error("Don't know how to handle arrays") | ||
} | ||
|
||
const parentQuasi = quasiPath.parentPath?.get('quasi') | ||
|
||
function asTag(quasiPath) { | ||
const value = quasiPath.parentPath.get('quasi').evaluate().value | ||
quasiPath.parentPath.replaceWith(evalToAST(value)) | ||
if (!parentQuasi) { | ||
throw new Error('No quasi path on parent') | ||
} | ||
|
||
if (Array.isArray(parentQuasi)) { | ||
throw new Error("Don't know how to handle arrays") | ||
} | ||
const value = parentQuasi.evaluate().value | ||
quasiPath.parentPath?.replaceWith(evalToAST(value)) | ||
} | ||
|
||
function asFunction(argumentsPaths) { | ||
function asFunction(argumentsPaths: NodePath[]) { | ||
const value = argumentsPaths[0].evaluate().value | ||
argumentsPaths[0].parentPath.replaceWith(evalToAST(value)) | ||
argumentsPaths[0].parentPath?.replaceWith(evalToAST(value)) | ||
} | ||
|
||
type NodeWithValue = Node & { | ||
value: any | ||
} | ||
|
||
function isNodeWithValue(node: Node): node is NodeWithValue { | ||
return Object.prototype.hasOwnProperty.call(node, 'value') | ||
} | ||
|
||
// eslint-disable-next-line no-unused-vars | ||
function asJSX({attributes, children}) { | ||
function asJSX({ | ||
attributes, | ||
children, | ||
}: { | ||
attributes: NodePath | NodePath[] | ||
children: NodePath | NodePath[] | undefined | ||
}) { | ||
// It's a shame you cannot use evaluate() with JSX | ||
const value = children[0].node.value | ||
children[0].parentPath.replaceWith(evalToAST(value)) | ||
if (!Array.isArray(children)) { | ||
throw new Error("Don't know how to handle single children") | ||
} | ||
const firstChild = children[0] | ||
if (!isNodeWithValue(firstChild.node)) { | ||
throw new Error("Don't know to handle nodes without values") | ||
} | ||
const value = firstChild.node.value | ||
firstChild.parentPath?.replaceWith(evalToAST(value)) | ||
} | ||
|
||
function evalToAST(value) { | ||
let x | ||
function evalToAST(value: Expression | null | undefined): Expression { | ||
let x: Record<string, unknown> = {} | ||
// eslint-disable-next-line | ||
eval(`x = ${value}`) | ||
return thingToAST(x) | ||
} | ||
|
||
function thingToAST(object) { | ||
function isVariableDeclaration( | ||
statement: Statement, | ||
): statement is VariableDeclaration { | ||
return statement.type === 'VariableDeclaration' | ||
} | ||
|
||
function thingToAST(object: Record<string, unknown>) { | ||
const fileNode = parse(`var x = ${JSON.stringify(object)}`) | ||
return fileNode.program.body[0].declarations[0].init | ||
const firstStatement = fileNode.program.body[0] | ||
|
||
if (!isVariableDeclaration(firstStatement)) { | ||
throw new Error('Only know how to handle VariableDeclarations') | ||
} | ||
|
||
const initDeclaration = firstStatement.declarations[0].init | ||
|
||
if (!initDeclaration) { | ||
throw new Error('Was expecting expression') | ||
} | ||
return initDeclaration | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,20 +1,38 @@ | ||
// adds "prefix-" to each `id` attribute | ||
const {createMacro} = require('../../') | ||
import {createMacro} from '../../' | ||
import { | ||
JSXElement, | ||
JSXExpressionContainer, | ||
JSXFragment, | ||
StringLiteral, | ||
} from '@babel/types' | ||
|
||
module.exports = createMacro(wrapWidget) | ||
|
||
function wrapWidget({references, babel}) { | ||
module.exports = createMacro(function wrapWidget({references, babel}) { | ||
const {types: t} = babel | ||
references.default.forEach(wrap => { | ||
wrap.parentPath.traverse({ | ||
wrap.parentPath?.traverse({ | ||
JSXAttribute(path) { | ||
const name = path.get('name') | ||
if (t.isJSXIdentifier(name) && name.node.name === 'id') { | ||
const value = path.get('value') | ||
if (t.isStringLiteral(value)) | ||
value.replaceWith(t.stringLiteral(`macro-${value.node.value}`)) | ||
if (isStringLiteral(value.node)) { | ||
value.replaceWith(t.stringLiteral(`macro-${value.node?.value}`)) | ||
} | ||
} | ||
}, | ||
}) | ||
}) | ||
}) | ||
|
||
function isStringLiteral( | ||
node: | ||
| JSXElement | ||
| JSXExpressionContainer | ||
| JSXFragment | ||
| StringLiteral | ||
| null | ||
| undefined, | ||
): node is StringLiteral { | ||
if (!node) return false | ||
return node.type === 'StringLiteral' | ||
} |
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,5 @@ | ||
const {createMacro} = require('../../') | ||
import {createMacro} from '../../' | ||
|
||
module.exports = createMacro(keepImportMacro) | ||
|
||
function keepImportMacro() { | ||
export default createMacro(function keepImportMacro() { | ||
return {keepImports: true} | ||
} | ||
}) |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,6 @@ | ||
// const printAST = require('ast-pretty-print') | ||
const {createMacro, MacroError} = require('../../') | ||
import {createMacro, MacroError} from '../../' | ||
|
||
module.exports = createMacro(evalMacro) | ||
|
||
function evalMacro() { | ||
export default createMacro(function evalMacro() { | ||
throw new MacroError('very helpful') | ||
} | ||
}) |
6 changes: 5 additions & 1 deletion
6
src/__tests__/fixtures/path-replace-issue/variable-assignment.ts
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,9 @@ | ||
import myEval from '../eval.macro' | ||
|
||
const result = myEval`+('4' + '2')` | ||
const result = myEval`+('4' + '2')` as number | ||
|
||
declare global { | ||
var result: number; | ||
} | ||
|
||
global.result = result |
15 changes: 6 additions & 9 deletions
15
src/__tests__/fixtures/primitive-config/configurable.macro.ts
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,7 @@ | ||
const {createMacro} = require('../../..') | ||
import { createMacro } from '../../..' | ||
|
||
const configName = 'configurableMacro' | ||
const realMacro = jest.fn() | ||
module.exports = createMacro(realMacro, {configName}) | ||
// for testing purposes only | ||
Object.assign(module.exports, { | ||
realMacro, | ||
configName, | ||
}) | ||
// exports for testing purposes only: | ||
export const configName = 'configurableMacro' | ||
export const realMacro = jest.fn() | ||
|
||
export default createMacro(realMacro, { configName }) |
Oops, something went wrong.