json-as 1.1.16 → 1.1.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +4 -0
- package/README.md +1 -1
- package/assembly/__tests__/namespace.spec.ts +63 -0
- package/assembly/test.tmp.ts +7 -0
- package/assembly/test.ts +2 -0
- package/package.json +5 -5
- package/run-tests.sh +17 -13
- package/transform/lib/index.js +32 -37
- package/transform/lib/index.js.map +1 -1
- package/transform/lib/types.js +103 -2
- package/transform/lib/types.js.map +1 -1
- package/transform/src/index.ts +36 -37
- package/transform/src/types.ts +182 -4
- package/transform/src/linkers/classes.ts +0 -50
package/transform/src/types.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { ClassDeclaration, Expression, FieldDeclaration, Source } from "assemblyscript/dist/assemblyscript.js";
|
|
1
|
+
import { ClassDeclaration, Expression, FieldDeclaration, Source, NodeKind, Node, NamespaceDeclaration, DeclarationStatement, TypeName, Parser, ImportStatement, CommonFlags } from "assemblyscript/dist/assemblyscript.js";
|
|
2
2
|
import { TypeAlias } from "./linkers/alias.js";
|
|
3
|
-
import {
|
|
3
|
+
import { stripNull } from "./index.js";
|
|
4
4
|
|
|
5
5
|
export enum PropertyFlags {
|
|
6
6
|
OmitNull,
|
|
@@ -75,14 +75,192 @@ export class Schema {
|
|
|
75
75
|
}
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
+
export class SourceSet {
|
|
79
|
+
private sources: Record<string, Src> = {};
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Get a stored source from the set, or create a new one and store it if it
|
|
83
|
+
* didn't exist.
|
|
84
|
+
* @param source AssemblyScript Source
|
|
85
|
+
* @returns Source object
|
|
86
|
+
*/
|
|
87
|
+
get(source: Source): Src {
|
|
88
|
+
let src = this.sources[source.internalPath];
|
|
89
|
+
if (!src) {
|
|
90
|
+
src = new Src(source, this);
|
|
91
|
+
this.sources[source.internalPath] = src;
|
|
92
|
+
}
|
|
93
|
+
return src;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
78
97
|
export class Src {
|
|
79
98
|
public internalPath: string;
|
|
99
|
+
public normalizedPath: string;
|
|
80
100
|
public schemas: Schema[];
|
|
81
101
|
public aliases: TypeAlias[];
|
|
82
|
-
public imports: Schema[];
|
|
83
102
|
public exports: Schema[];
|
|
84
|
-
|
|
103
|
+
private nodeMap: Map<Node, NamespaceDeclaration[]> = new Map<Node, NamespaceDeclaration[]>();
|
|
104
|
+
private classes: Record<string, ClassDeclaration> = {};
|
|
105
|
+
private imports: ImportStatement[] = [];
|
|
106
|
+
|
|
107
|
+
constructor(
|
|
108
|
+
source: Source,
|
|
109
|
+
private sourceSet: SourceSet,
|
|
110
|
+
) {
|
|
85
111
|
this.internalPath = source.internalPath;
|
|
112
|
+
this.normalizedPath = source.normalizedPath;
|
|
86
113
|
this.aliases = TypeAlias.getAliases(source);
|
|
114
|
+
this.traverse(source.statements, []);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Traverse source nodes and finds all classes and imports, and which namespaces they exist under.
|
|
119
|
+
* @param nodes Nodes to traverse.
|
|
120
|
+
* @param path The current path of namespace declarations leading to the nodes.
|
|
121
|
+
*/
|
|
122
|
+
private traverse(nodes: Node[], path: NamespaceDeclaration[]) {
|
|
123
|
+
for (let node of nodes) {
|
|
124
|
+
switch (node.kind) {
|
|
125
|
+
case NodeKind.NamespaceDeclaration:
|
|
126
|
+
const namespaceDeclaration = node as NamespaceDeclaration;
|
|
127
|
+
this.traverse(namespaceDeclaration.members, [...path, namespaceDeclaration]);
|
|
128
|
+
break;
|
|
129
|
+
case NodeKind.ClassDeclaration:
|
|
130
|
+
const classDeclaration = node as ClassDeclaration;
|
|
131
|
+
this.classes[this.qualifiedName(classDeclaration, path)] = classDeclaration;
|
|
132
|
+
break;
|
|
133
|
+
case NodeKind.Import:
|
|
134
|
+
const importStatement = node as ImportStatement;
|
|
135
|
+
this.imports.push(importStatement);
|
|
136
|
+
break;
|
|
137
|
+
}
|
|
138
|
+
this.nodeMap.set(node, path);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Get the qualified name (eg. "Namespace.BaseObject") for a class.
|
|
144
|
+
* @param node Class declaration.
|
|
145
|
+
* @returns Qualified name
|
|
146
|
+
*/
|
|
147
|
+
getQualifiedName(node: DeclarationStatement): string {
|
|
148
|
+
return this.qualifiedName(node, this.nodeMap.get(node));
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Get a class declaration by its qualified name.
|
|
153
|
+
* @param qualifiedName Qualified named (eg. "Namespace.BaseObject")
|
|
154
|
+
* @returns Class declaration or null if not found.
|
|
155
|
+
*/
|
|
156
|
+
getClass(qualifiedName: string): ClassDeclaration | null {
|
|
157
|
+
return this.classes[qualifiedName] || null;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Get imported class from other sources in the parser.
|
|
162
|
+
* @param qualifiedName Qualified name of class.
|
|
163
|
+
* @param parser AssemblyScript parser.
|
|
164
|
+
* @returns Class declaration or null if not found.
|
|
165
|
+
*/
|
|
166
|
+
getImportedClass(qualifiedName: string, parser: Parser): ClassDeclaration | null {
|
|
167
|
+
for (const stmt of this.imports) {
|
|
168
|
+
const externalSource = parser.sources.filter((src) => src.internalPath != this.internalPath).find((src) => src.internalPath == stmt.internalPath);
|
|
169
|
+
if (!externalSource) continue;
|
|
170
|
+
|
|
171
|
+
const source = this.sourceSet.get(externalSource);
|
|
172
|
+
const classDeclaration = source.getClass(qualifiedName);
|
|
173
|
+
if (classDeclaration && classDeclaration.flags & CommonFlags.Export) {
|
|
174
|
+
return classDeclaration;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
return null;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Gets a unique path string to the node by combining the internalPath with
|
|
182
|
+
* the qualified name of the node.
|
|
183
|
+
* @param node DeclarationStatement
|
|
184
|
+
*/
|
|
185
|
+
getFullPath(node: DeclarationStatement): string {
|
|
186
|
+
return this.internalPath + "/" + this.getQualifiedName(node);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Resolved the qualified name of the extended class for a class
|
|
191
|
+
* declaration.
|
|
192
|
+
* @param classDeclaration Class declaration that extends another class.
|
|
193
|
+
* @returns Qualified name of the extended class, or empty string if not extending any class.
|
|
194
|
+
*/
|
|
195
|
+
resolveExtendsName(classDeclaration: ClassDeclaration): string {
|
|
196
|
+
const parents = this.nodeMap.get(classDeclaration);
|
|
197
|
+
if (!classDeclaration.extendsType || !parents) {
|
|
198
|
+
return "";
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
const name = classDeclaration.extendsType.name.identifier.text;
|
|
202
|
+
const extendsName = this.getIdentifier(classDeclaration.extendsType.name);
|
|
203
|
+
|
|
204
|
+
// Reverse walk to find first class or namespace that matches the first part
|
|
205
|
+
// of type name.
|
|
206
|
+
for (let i = parents.length - 1; i >= 0; i--) {
|
|
207
|
+
const parent = parents[i];
|
|
208
|
+
for (let node of parent.members) {
|
|
209
|
+
if (name == this.getNamespaceOrClassName(node)) {
|
|
210
|
+
// Add namespace path to the extendsName.
|
|
211
|
+
return (
|
|
212
|
+
parents
|
|
213
|
+
.slice(0, i + 1)
|
|
214
|
+
.map((p) => p.name.text)
|
|
215
|
+
.join(".") +
|
|
216
|
+
"." +
|
|
217
|
+
extendsName
|
|
218
|
+
);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
// No matching class or namespace found. Just use the extendsName.
|
|
223
|
+
return extendsName;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Get the qualified name (eg "Namespace.BaseObject") of a class.
|
|
228
|
+
* @param node Class declaration.
|
|
229
|
+
* @param parents Array of namespace parents.
|
|
230
|
+
* @returns Qualified name
|
|
231
|
+
*/
|
|
232
|
+
private qualifiedName(node: DeclarationStatement, parents: NamespaceDeclaration[]): string {
|
|
233
|
+
return parents?.length ? parents.map((p) => p.name.text).join(".") + "." + node.name.text : node.name.text;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Checks if the node is either a namespace or class, and returns the simple
|
|
238
|
+
* name of the node.
|
|
239
|
+
* @param node Node to check
|
|
240
|
+
* @returns Name of namespace or class, or empty string if other type of node.
|
|
241
|
+
*/
|
|
242
|
+
private getNamespaceOrClassName(node: Node): string {
|
|
243
|
+
switch (node.kind) {
|
|
244
|
+
case NodeKind.NamespaceDeclaration:
|
|
245
|
+
return (node as DeclarationStatement).name.text;
|
|
246
|
+
case NodeKind.ClassDeclaration:
|
|
247
|
+
return (node as DeclarationStatement).name.text;
|
|
248
|
+
}
|
|
249
|
+
return "";
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* Get the full name (eg. "Namespace.Base") of a type name such as an
|
|
254
|
+
* extendedType.
|
|
255
|
+
* @param typeName Type name
|
|
256
|
+
* @returns Full name
|
|
257
|
+
*/
|
|
258
|
+
private getIdentifier(typeName: TypeName): string {
|
|
259
|
+
let names = [];
|
|
260
|
+
while (typeName) {
|
|
261
|
+
names.push(typeName.identifier.text);
|
|
262
|
+
typeName = typeName.next;
|
|
263
|
+
}
|
|
264
|
+
return names.join(".");
|
|
87
265
|
}
|
|
88
266
|
}
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import { ClassDeclaration, CommonFlags, NodeKind, Parser, Source } from "assemblyscript/dist/assemblyscript.js";
|
|
2
|
-
import { Visitor } from "../visitor.js";
|
|
3
|
-
import { getImports } from "./imports.js";
|
|
4
|
-
|
|
5
|
-
export function getImportedClass(name: string, source: Source, parser: Parser): ClassDeclaration | null {
|
|
6
|
-
for (const stmt of getImports(source)) {
|
|
7
|
-
const externalSource = parser.sources.filter((src) => src.internalPath != source.internalPath).find((src) => src.internalPath == stmt.internalPath);
|
|
8
|
-
if (!externalSource) continue;
|
|
9
|
-
|
|
10
|
-
const classDeclaration = ClassGetter.getClass(name, externalSource);
|
|
11
|
-
if (!classDeclaration) continue;
|
|
12
|
-
if (!(classDeclaration.flags & CommonFlags.Export)) continue;
|
|
13
|
-
return classDeclaration;
|
|
14
|
-
}
|
|
15
|
-
return null;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
class ClassGetter extends Visitor {
|
|
19
|
-
static SN: ClassGetter = new ClassGetter();
|
|
20
|
-
|
|
21
|
-
private classes: ClassDeclaration[] = [];
|
|
22
|
-
|
|
23
|
-
visitClassDeclaration(node: ClassDeclaration): void {
|
|
24
|
-
this.classes.push(node);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
// visitTypeName(node: TypeName, ref?: Node | null): void {}
|
|
28
|
-
// visitParameter(node: ParameterNode, ref?: Node | null): void {}
|
|
29
|
-
// visitFunctionTypeNode(node: FunctionTypeNode, ref?: Node | null): void {}
|
|
30
|
-
// visitNamedTypeNode(node: NamedTypeNode, ref?: Node | null): void {}
|
|
31
|
-
|
|
32
|
-
static getClass(name: string, source: Source): ClassDeclaration | null {
|
|
33
|
-
return ClassGetter.getClasses(source).find((c) => c.name.text == name) || null;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
static getClasses(source: Source): ClassDeclaration[] {
|
|
37
|
-
// ClassGetter.SN.classes = [];
|
|
38
|
-
// ClassGetter.SN.visit(source);
|
|
39
|
-
// return ClassGetter.SN.classes;
|
|
40
|
-
return source.statements.filter((stmt) => stmt.kind == NodeKind.ClassDeclaration) as ClassDeclaration[];
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
export function getClasses(source: Source): ClassDeclaration[] {
|
|
45
|
-
return ClassGetter.getClasses(source);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
export function getClass(name: string, source: Source): ClassDeclaration | null {
|
|
49
|
-
return ClassGetter.getClass(name, source);
|
|
50
|
-
}
|