UNPKG

4.93 kBPlain TextView Raw
1import * as ts from 'typescript';
2
3export interface ParsedNode {
4 kind: ts.SyntaxKind
5 _kind: string
6 name?: string
7 value?: any
8 body?: ParsedNode[]
9}
10
11function walk(sourceFile: ts.SourceFile): ParsedNode[] {
12
13 const stack : Array<ParsedNode> = [];
14 const elementStack : Array<ParsedNode> = [];
15
16 function push(element) {
17 const parent = elementStack[elementStack.length - 1];
18 const siblings = (parent && parent.body) ? parent.body : stack;
19 siblings.push(element);
20 }
21
22 eachProp(sourceFile);
23
24 return stack;
25
26 function addFromArrayElement(incoming) {
27 switch(incoming.kind) {
28 case ts.SyntaxKind.NullKeyword:
29 case ts.SyntaxKind.TrueKeyword:
30 case ts.SyntaxKind.FalseKeyword:
31 case ts.SyntaxKind.NumericLiteral:
32 case ts.SyntaxKind.StringLiteral: {
33 push(literalTypeFromArrayElement(incoming, incoming.kind));
34 break;
35 }
36 case ts.SyntaxKind.ObjectLiteralExpression: {
37 const elem = {
38 kind: ts.SyntaxKind.ObjectLiteralExpression,
39 _kind: `ObjectLiteralExpression`,
40 body: [],
41 };
42 push(elem);
43 elementStack.push(elem);
44 eachProp(incoming.properties);
45 elementStack.pop();
46 break;
47 }
48 case ts.SyntaxKind.ArrayLiteralExpression: {
49 const elem = {
50 kind: ts.SyntaxKind.ArrayLiteralExpression,
51 _kind: `ArrayLiteralExpression`,
52 body: [],
53 };
54 push(elem);
55 elementStack.push(elem);
56 eachProp(incoming.elements);
57 elementStack.pop();
58 break;
59 }
60 }
61 }
62
63 function eachProp(properties) {
64 properties.forEach(function (prop) {
65 if (!prop.initializer) {
66 return addFromArrayElement(prop);
67 } else {
68 switch (prop.initializer.kind) {
69 case ts.SyntaxKind.TrueKeyword:
70 case ts.SyntaxKind.FalseKeyword:
71 case ts.SyntaxKind.NullKeyword:
72 case ts.SyntaxKind.StringLiteral:
73 case ts.SyntaxKind.NumericLiteral: {
74 push(literalTypeFromProp(prop, prop.initializer.kind));
75 break;
76 }
77 case ts.SyntaxKind.PrefixUnaryExpression: {
78 push(literalTypeFromProp(prop, ts.SyntaxKind.NumericLiteral));
79 break;
80 }
81 case ts.SyntaxKind.ObjectLiteralExpression: {
82 // console.log('OBJ', prop.name.text);
83 const elem = {
84 name: prop.name.text,
85 body: [],
86 kind: ts.SyntaxKind.ObjectLiteralExpression,
87 _kind: `ObjectLiteralExpression`
88 };
89 push(elem);
90 elementStack.push(elem);
91 eachProp(prop.initializer.properties);
92 elementStack.pop();
93 break;
94 }
95 case ts.SyntaxKind.ArrayLiteralExpression: {
96 const elem = {
97 name: prop.name.text,
98 body: [],
99 kind: ts.SyntaxKind.ArrayLiteralExpression,
100 _kind: `ArrayLiteralExpression`
101 };
102 push(elem);
103 elementStack.push(elem);
104 eachProp(prop.initializer.elements);
105 elementStack.pop();
106 break;
107 }
108 }
109 }
110 });
111 }
112
113 function literalTypeFromProp(prop, kind) {
114 return {
115 name: prop.name.text,
116 value: prop.initializer.text,
117 kind: kind,
118 }
119 }
120
121 function literalTypeFromArrayElement(element, kind) {
122 return {
123 kind,
124 name: element.text,
125 value: element.text,
126 }
127 }
128}
129
130export function parse(string): any[] {
131 const input = `const ROOTOBJ = ${string}`;
132 let sourceFile : ts.SourceFile = ts.createSourceFile('json.ts', input, ts.ScriptTarget.ES2015, /*setParentNodes */ true);
133 // delint it
134 const _json = sourceFile.statements[0] as any;
135 // console.log(sourceFile.statements[0].declarationList.declarations[0].initializer.properties);
136 // elementStack.push({name: 'root', body: []});
137 const stack = walk(_json.declarationList.declarations[0].initializer.properties);
138 return stack;
139}