1 |
|
2 | import AST, { SourceFile, Symbol, ts, Identifier } from 'ts-simple-ast';
|
3 |
|
4 | import path from 'path';
|
5 |
|
6 | export interface Globals {
|
7 | readonly Array: Symbol;
|
8 | readonly Buffer: Symbol;
|
9 | readonly process: Symbol;
|
10 | readonly AccountBase: Symbol;
|
11 | readonly AssetBase: Symbol;
|
12 | readonly AttributeBase: Symbol;
|
13 | readonly BlockBase: Symbol;
|
14 | readonly ContractBase: Symbol;
|
15 | readonly HeaderBase: Symbol;
|
16 | readonly InputBase: Symbol;
|
17 | readonly OutputBase: Symbol;
|
18 | readonly TransactionBase: Symbol;
|
19 | readonly ValidatorBase: Symbol;
|
20 | readonly StorageContextBase: Symbol;
|
21 | readonly StorageIteratorBase: Symbol;
|
22 | readonly syscall: Symbol;
|
23 | }
|
24 |
|
25 | const findInterfaceFile = (ast: AST, name: string): SourceFile | undefined => {
|
26 | const files = ast.getSourceFiles();
|
27 | return files.find((file) => {
|
28 | if (!file.isDeclarationFile()) {
|
29 | return false;
|
30 | }
|
31 |
|
32 | let bufferInterface = file.getInterface(name);
|
33 | const globalNamespace = file.getNamespace('global');
|
34 | let isGlobalAugmentation = false;
|
35 | if (bufferInterface == null && globalNamespace != null) {
|
36 | bufferInterface = globalNamespace.getInterface(name);
|
37 | isGlobalAugmentation = true;
|
38 | }
|
39 |
|
40 | if (bufferInterface == null) {
|
41 | return false;
|
42 | }
|
43 |
|
44 | return (
|
45 | isGlobalAugmentation ||
|
46 | (bufferInterface.compilerNode.flags & ts.NodeFlags.GlobalAugmentation) !==
|
47 | 0
|
48 | );
|
49 | });
|
50 | };
|
51 |
|
52 | export const getGlobals = (ast: AST): Globals => {
|
53 | let bufferFile = findInterfaceFile(ast, 'Buffer');
|
54 | if (bufferFile == null) {
|
55 | bufferFile = ast.addExistingSourceFileIfExists(
|
56 | require.resolve('@types/node/index.d.ts'),
|
57 | );
|
58 | }
|
59 | if (bufferFile == null) {
|
60 | throw new Error('Could not find Buffer');
|
61 | }
|
62 | const buffer = bufferFile.getInterfaceOrThrow('Buffer');
|
63 |
|
64 | const typeChecker = ast.getTypeChecker().compilerObject as any;
|
65 |
|
66 | const array = new Symbol(
|
67 |
|
68 | ast.global,
|
69 | typeChecker.createArrayType(typeChecker.getAnyType()).symbol as ts.Symbol,
|
70 | ).getDeclaredType();
|
71 |
|
72 | let neoFile = findInterfaceFile(ast, 'AccountBase');
|
73 | if (neoFile == null) {
|
74 | ast.addExistingSourceFiles(
|
75 | path.join(
|
76 | path.dirname(require.resolve('@neo-one/smart-contract')),
|
77 | '**',
|
78 | '*.ts',
|
79 | ),
|
80 | );
|
81 | }
|
82 |
|
83 | neoFile = findInterfaceFile(ast, 'AccountBase');
|
84 | if (neoFile == null) {
|
85 | throw new Error('Could not find NEO type definition file');
|
86 | }
|
87 |
|
88 | const neoGlobal = neoFile.getNamespaceOrThrow('global');
|
89 |
|
90 | return {
|
91 | Array: array.getSymbolOrThrow(),
|
92 | Buffer: buffer.getSymbolOrThrow(),
|
93 | process: bufferFile
|
94 | .getVariableDeclarationOrThrow('process')
|
95 | .getSymbolOrThrow(),
|
96 | AccountBase: neoGlobal
|
97 | .getInterfaceOrThrow('AccountBase')
|
98 | .getSymbolOrThrow(),
|
99 | AssetBase: neoGlobal.getInterfaceOrThrow('AssetBase').getSymbolOrThrow(),
|
100 | AttributeBase: neoGlobal
|
101 | .getInterfaceOrThrow('AttributeBase')
|
102 | .getSymbolOrThrow(),
|
103 | BlockBase: neoGlobal.getInterfaceOrThrow('BlockBase').getSymbolOrThrow(),
|
104 | ContractBase: neoGlobal
|
105 | .getInterfaceOrThrow('ContractBase')
|
106 | .getSymbolOrThrow(),
|
107 | HeaderBase: neoGlobal.getInterfaceOrThrow('HeaderBase').getSymbolOrThrow(),
|
108 | InputBase: neoGlobal.getInterfaceOrThrow('InputBase').getSymbolOrThrow(),
|
109 | OutputBase: neoGlobal.getInterfaceOrThrow('OutputBase').getSymbolOrThrow(),
|
110 | TransactionBase: neoGlobal
|
111 | .getInterfaceOrThrow('TransactionBase')
|
112 | .getSymbolOrThrow(),
|
113 | ValidatorBase: neoGlobal
|
114 | .getInterfaceOrThrow('ValidatorBase')
|
115 | .getSymbolOrThrow(),
|
116 | StorageContextBase: neoGlobal
|
117 | .getInterfaceOrThrow('StorageContextBase')
|
118 | .getSymbolOrThrow(),
|
119 | StorageIteratorBase: neoGlobal
|
120 | .getInterfaceOrThrow('StorageIteratorBase')
|
121 | .getSymbolOrThrow(),
|
122 | syscall: neoGlobal.getFunctionOrThrow('syscall').getSymbolOrThrow(),
|
123 | };
|
124 | };
|
125 |
|
126 | export interface Libs {
|
127 | readonly SmartContract: Symbol;
|
128 | readonly MapStorage: Symbol;
|
129 | readonly SetStorage: Symbol;
|
130 | readonly Fixed: Symbol;
|
131 | readonly constant: Symbol;
|
132 | readonly verify: Symbol;
|
133 | }
|
134 |
|
135 | const findLibFile = (ast: AST): SourceFile | undefined => {
|
136 | const files = ast.getSourceFiles();
|
137 | return files.find((file) => file.getClass('MapStorage') != null);
|
138 | };
|
139 |
|
140 | export const getLibs = (ast: AST): Libs => {
|
141 | let libFileIn = findLibFile(ast);
|
142 | if (libFileIn == null) {
|
143 | ast.addExistingSourceFiles(
|
144 | path.join(
|
145 | path.dirname(require.resolve('@neo-one/smart-contract')),
|
146 | '**',
|
147 | '*.ts',
|
148 | ),
|
149 | );
|
150 | }
|
151 |
|
152 | libFileIn = findLibFile(ast);
|
153 | if (libFileIn == null) {
|
154 | throw new Error('Could not find NEO lib file');
|
155 | }
|
156 |
|
157 | const libFile = libFileIn;
|
158 |
|
159 | return {
|
160 | get SmartContract(): Symbol {
|
161 | return libFile.getClassOrThrow('SmartContract').getSymbolOrThrow();
|
162 | },
|
163 | get MapStorage(): Symbol {
|
164 | return libFile.getClassOrThrow('MapStorage').getSymbolOrThrow();
|
165 | },
|
166 | get SetStorage(): Symbol {
|
167 | return libFile.getClassOrThrow('SetStorage').getSymbolOrThrow();
|
168 | },
|
169 | get Fixed(): Symbol {
|
170 | return libFile.getTypeAliasOrThrow('Fixed').getSymbolOrThrow();
|
171 | },
|
172 | get constant(): Symbol {
|
173 | return libFile.getFunctionOrThrow('constant').getSymbolOrThrow();
|
174 | },
|
175 | get verify(): Symbol {
|
176 | return libFile.getFunctionOrThrow('verify').getSymbolOrThrow();
|
177 | },
|
178 | };
|
179 | };
|
180 |
|
181 | export interface LibAliases {
|
182 | readonly Address: Set<Identifier>;
|
183 | readonly Hash256: Set<Identifier>;
|
184 | readonly Signature: Set<Identifier>;
|
185 | readonly PublicKey: Set<Identifier>;
|
186 | }
|
187 |
|
188 | export const getLibAliases = (ast: AST): LibAliases => {
|
189 | let libFileIn = findLibFile(ast);
|
190 | if (libFileIn == null) {
|
191 | ast.addExistingSourceFiles(
|
192 | path.join(
|
193 | path.dirname(require.resolve('@neo-one/smart-contract')),
|
194 | '**',
|
195 | '*.ts',
|
196 | ),
|
197 | );
|
198 | }
|
199 |
|
200 | libFileIn = findLibFile(ast);
|
201 | if (libFileIn == null) {
|
202 | throw new Error('Could not find NEO lib file');
|
203 | }
|
204 |
|
205 | const libFile = libFileIn;
|
206 |
|
207 | return {
|
208 | get Address(): Set<Identifier> {
|
209 | return new Set(libFile
|
210 | .getTypeAliasOrThrow('Address')
|
211 | .getReferencingNodes() as Identifier[]);
|
212 | },
|
213 | get Hash256(): Set<Identifier> {
|
214 | return new Set(libFile
|
215 | .getTypeAliasOrThrow('Hash256')
|
216 | .getReferencingNodes() as Identifier[]);
|
217 | },
|
218 | get Signature(): Set<Identifier> {
|
219 | return new Set(libFile
|
220 | .getTypeAliasOrThrow('Signature')
|
221 | .getReferencingNodes() as Identifier[]);
|
222 | },
|
223 | get PublicKey(): Set<Identifier> {
|
224 | return new Set(libFile
|
225 | .getTypeAliasOrThrow('PublicKey')
|
226 | .getReferencingNodes() as Identifier[]);
|
227 | },
|
228 | };
|
229 | };
|