Created
August 3, 2019 13:44
-
-
Save kaymccormick/d86e06889d3945e9183fb3e3d8eb4a00 to your computer and use it in GitHub Desktop.
recursively copy an ast-types AST tree, in typescript
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
import {visit,getFieldNames, getFieldValue, eachField, namedTypes, builders} from 'ast-types'; | |
import { NodePath } from 'ast-types/lib/node-path'; | |
import { Map, List, Set} from 'immutable'; | |
import { ValueKind } from './types'; | |
export type CopyTreeResult = Map<string, ValueKind>; | |
export function copyTree(node: namedTypes.Node, | |
report?: (arg: string) => void, | |
level: number = 0): CopyTreeResult { | |
let cache: List<Map<string, any>> = List<Map<string, any>>(); | |
let depth = 0; | |
visit(node, { | |
visitNode(path: NodePath<namedTypes.Node>): any { | |
console.log(`${path.node.type} ${path.name} ${path.parentPath.name}`) | |
depth++; | |
this.traverse(path); | |
depth--; | |
if(cache.get(depth + 1) ===undefined ) { | |
cache= cache.set(depth + 1, Map<string, any>()); | |
} | |
if(cache.get(depth) === undefined ) { | |
cache= cache.set(depth, Map<string, any>()); | |
} | |
const anode = path.node; | |
//@ts-ignore | |
if(!namedTypes[anode.type].check(anode)) { | |
throw new Error('invalid node'); | |
} | |
let nary: Set<string> = Set<string>(getFieldNames(anode)); | |
nary = nary.subtract(cache.get(depth + 1)!.keySeq()); | |
const result: Map<string, any> = Map<string, any>( | |
nary.map(fName => [fName, getFieldValue(anode, fName)])) | |
.merge(cache.get(depth + 1)!); | |
cache = cache.delete(depth + 1); | |
if(typeof path.name === 'string') { | |
cache = cache.set(depth, | |
cache.get(depth)!.set(path.name, result)); | |
} else { | |
const key = path.parentPath.name; | |
let ary = cache.get(depth)!.get(path.parentPath.name) | |
|| List<Map<string, any>>(); | |
ary = ary.set(path.name, result); | |
cache = cache.set(depth, | |
cache.get(depth)!.set(path.parentPath.name, ary)); | |
} | |
}, | |
}); | |
const result = cache.get(0)!.get('root'); | |
console.log(JSON.stringify(result,null, 4)); | |
return result; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment