@bscotch/gml-parser 1.14.2
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/LICENSE.md +29 -0
- package/README.md +151 -0
- package/assets/GmlSpec.xml +11419 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -0
- package/dist/jsdoc.d.ts +79 -0
- package/dist/jsdoc.d.ts.map +1 -0
- package/dist/jsdoc.feather.d.ts +23 -0
- package/dist/jsdoc.feather.d.ts.map +1 -0
- package/dist/jsdoc.feather.js +143 -0
- package/dist/jsdoc.feather.js.map +1 -0
- package/dist/jsdoc.js +468 -0
- package/dist/jsdoc.js.map +1 -0
- package/dist/jsdoc.test.d.ts +2 -0
- package/dist/jsdoc.test.d.ts.map +1 -0
- package/dist/jsdoc.test.js +185 -0
- package/dist/jsdoc.test.js.map +1 -0
- package/dist/lexer.d.ts +3 -0
- package/dist/lexer.d.ts.map +1 -0
- package/dist/lexer.js +14 -0
- package/dist/lexer.js.map +1 -0
- package/dist/lexer.test.d.ts +2 -0
- package/dist/lexer.test.d.ts.map +1 -0
- package/dist/lexer.test.js +78 -0
- package/dist/lexer.test.js.map +1 -0
- package/dist/lib.objects.d.ts +190 -0
- package/dist/lib.objects.d.ts.map +1 -0
- package/dist/lib.objects.js +242 -0
- package/dist/lib.objects.js.map +1 -0
- package/dist/logger.d.ts +13 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +14 -0
- package/dist/logger.js.map +1 -0
- package/dist/modules.d.ts +19 -0
- package/dist/modules.d.ts.map +1 -0
- package/dist/modules.js +320 -0
- package/dist/modules.js.map +1 -0
- package/dist/modules.test.d.ts +2 -0
- package/dist/modules.test.d.ts.map +1 -0
- package/dist/modules.test.js +57 -0
- package/dist/modules.test.js.map +1 -0
- package/dist/modules.types.d.ts +78 -0
- package/dist/modules.types.d.ts.map +1 -0
- package/dist/modules.types.js +2 -0
- package/dist/modules.types.js.map +1 -0
- package/dist/modules.util.d.ts +5 -0
- package/dist/modules.util.d.ts.map +1 -0
- package/dist/modules.util.js +13 -0
- package/dist/modules.util.js.map +1 -0
- package/dist/parser.d.ts +121 -0
- package/dist/parser.d.ts.map +1 -0
- package/dist/parser.js +571 -0
- package/dist/parser.js.map +1 -0
- package/dist/parser.test.d.ts +2 -0
- package/dist/parser.test.d.ts.map +1 -0
- package/dist/parser.test.js +143 -0
- package/dist/parser.test.js.map +1 -0
- package/dist/parser.utility.d.ts +29 -0
- package/dist/parser.utility.d.ts.map +1 -0
- package/dist/parser.utility.js +125 -0
- package/dist/parser.utility.js.map +1 -0
- package/dist/project.asset.d.ts +115 -0
- package/dist/project.asset.d.ts.map +1 -0
- package/dist/project.asset.js +802 -0
- package/dist/project.asset.js.map +1 -0
- package/dist/project.code.d.ts +130 -0
- package/dist/project.code.d.ts.map +1 -0
- package/dist/project.code.js +570 -0
- package/dist/project.code.js.map +1 -0
- package/dist/project.d.ts +533 -0
- package/dist/project.d.ts.map +1 -0
- package/dist/project.diagnostics.d.ts +32 -0
- package/dist/project.diagnostics.d.ts.map +1 -0
- package/dist/project.diagnostics.js +23 -0
- package/dist/project.diagnostics.js.map +1 -0
- package/dist/project.js +1216 -0
- package/dist/project.js.map +1 -0
- package/dist/project.location.d.ts +133 -0
- package/dist/project.location.d.ts.map +1 -0
- package/dist/project.location.js +219 -0
- package/dist/project.location.js.map +1 -0
- package/dist/project.native.d.ts +26 -0
- package/dist/project.native.d.ts.map +1 -0
- package/dist/project.native.js +321 -0
- package/dist/project.native.js.map +1 -0
- package/dist/project.spec.d.ts +1298 -0
- package/dist/project.spec.d.ts.map +1 -0
- package/dist/project.spec.js +263 -0
- package/dist/project.spec.js.map +1 -0
- package/dist/project.test.d.ts +2 -0
- package/dist/project.test.d.ts.map +1 -0
- package/dist/project.test.js +633 -0
- package/dist/project.test.js.map +1 -0
- package/dist/shaderDefaults.d.ts +3 -0
- package/dist/shaderDefaults.d.ts.map +1 -0
- package/dist/shaderDefaults.js +32 -0
- package/dist/shaderDefaults.js.map +1 -0
- package/dist/signifiers.d.ts +54 -0
- package/dist/signifiers.d.ts.map +1 -0
- package/dist/signifiers.flags.d.ts +38 -0
- package/dist/signifiers.flags.d.ts.map +1 -0
- package/dist/signifiers.flags.js +131 -0
- package/dist/signifiers.flags.js.map +1 -0
- package/dist/signifiers.js +117 -0
- package/dist/signifiers.js.map +1 -0
- package/dist/spine.d.ts +28 -0
- package/dist/spine.d.ts.map +1 -0
- package/dist/spine.js +64 -0
- package/dist/spine.js.map +1 -0
- package/dist/spine.test.d.ts +2 -0
- package/dist/spine.test.d.ts.map +1 -0
- package/dist/spine.test.js +420 -0
- package/dist/spine.test.js.map +1 -0
- package/dist/spine.types.d.ts +89 -0
- package/dist/spine.types.d.ts.map +1 -0
- package/dist/spine.types.js +2 -0
- package/dist/spine.types.js.map +1 -0
- package/dist/test.lib.d.ts +3 -0
- package/dist/test.lib.d.ts.map +1 -0
- package/dist/test.lib.js +16 -0
- package/dist/test.lib.js.map +1 -0
- package/dist/tokens.categories.d.ts +22 -0
- package/dist/tokens.categories.d.ts.map +1 -0
- package/dist/tokens.categories.js +78 -0
- package/dist/tokens.categories.js.map +1 -0
- package/dist/tokens.code.d.ts +2 -0
- package/dist/tokens.code.d.ts.map +1 -0
- package/dist/tokens.code.js +523 -0
- package/dist/tokens.code.js.map +1 -0
- package/dist/tokens.d.ts +130 -0
- package/dist/tokens.d.ts.map +1 -0
- package/dist/tokens.js +13 -0
- package/dist/tokens.js.map +1 -0
- package/dist/tokens.lib.d.ts +15 -0
- package/dist/tokens.lib.d.ts.map +1 -0
- package/dist/tokens.lib.js +12 -0
- package/dist/tokens.lib.js.map +1 -0
- package/dist/tokens.shared.d.ts +4 -0
- package/dist/tokens.shared.d.ts.map +1 -0
- package/dist/tokens.shared.js +35 -0
- package/dist/tokens.shared.js.map +1 -0
- package/dist/tokens.strings.d.ts +5 -0
- package/dist/tokens.strings.d.ts.map +1 -0
- package/dist/tokens.strings.js +111 -0
- package/dist/tokens.strings.js.map +1 -0
- package/dist/types.checks.d.ts +50 -0
- package/dist/types.checks.d.ts.map +1 -0
- package/dist/types.checks.js +246 -0
- package/dist/types.checks.js.map +1 -0
- package/dist/types.d.ts +152 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.feather.d.ts +21 -0
- package/dist/types.feather.d.ts.map +1 -0
- package/dist/types.feather.js +156 -0
- package/dist/types.feather.js.map +1 -0
- package/dist/types.hover.d.ts +4 -0
- package/dist/types.hover.d.ts.map +1 -0
- package/dist/types.hover.js +99 -0
- package/dist/types.hover.js.map +1 -0
- package/dist/types.js +457 -0
- package/dist/types.js.map +1 -0
- package/dist/types.primitives.d.ts +10 -0
- package/dist/types.primitives.d.ts.map +1 -0
- package/dist/types.primitives.js +88 -0
- package/dist/types.primitives.js.map +1 -0
- package/dist/types.sprites.d.ts +8 -0
- package/dist/types.sprites.d.ts.map +1 -0
- package/dist/types.sprites.js +417 -0
- package/dist/types.sprites.js.map +1 -0
- package/dist/types.test.d.ts +2 -0
- package/dist/types.test.d.ts.map +1 -0
- package/dist/types.test.js +62 -0
- package/dist/types.test.js.map +1 -0
- package/dist/util.d.ts +50 -0
- package/dist/util.d.ts.map +1 -0
- package/dist/util.js +168 -0
- package/dist/util.js.map +1 -0
- package/dist/util.test.d.ts +3 -0
- package/dist/util.test.d.ts.map +1 -0
- package/dist/util.test.js +63 -0
- package/dist/util.test.js.map +1 -0
- package/dist/visitor.assign.d.ts +24 -0
- package/dist/visitor.assign.d.ts.map +1 -0
- package/dist/visitor.assign.js +112 -0
- package/dist/visitor.assign.js.map +1 -0
- package/dist/visitor.d.ts +89 -0
- package/dist/visitor.d.ts.map +1 -0
- package/dist/visitor.functionExpression.d.ts +7 -0
- package/dist/visitor.functionExpression.d.ts.map +1 -0
- package/dist/visitor.functionExpression.js +216 -0
- package/dist/visitor.functionExpression.js.map +1 -0
- package/dist/visitor.globals.d.ts +59 -0
- package/dist/visitor.globals.d.ts.map +1 -0
- package/dist/visitor.globals.js +271 -0
- package/dist/visitor.globals.js.map +1 -0
- package/dist/visitor.identifierAccessor.d.ts +6 -0
- package/dist/visitor.identifierAccessor.d.ts.map +1 -0
- package/dist/visitor.identifierAccessor.js +381 -0
- package/dist/visitor.identifierAccessor.js.map +1 -0
- package/dist/visitor.js +605 -0
- package/dist/visitor.js.map +1 -0
- package/dist/visitor.processor.d.ts +66 -0
- package/dist/visitor.processor.d.ts.map +1 -0
- package/dist/visitor.processor.js +147 -0
- package/dist/visitor.processor.js.map +1 -0
- package/package.json +63 -0
|
@@ -0,0 +1,633 @@
|
|
|
1
|
+
import { expect } from 'chai';
|
|
2
|
+
import { logger } from './logger.js';
|
|
3
|
+
import { Project } from './project.js';
|
|
4
|
+
import { Native } from './project.native.js';
|
|
5
|
+
import { Signifier } from './signifiers.js';
|
|
6
|
+
import { resetSandbox } from './test.lib.js';
|
|
7
|
+
import { Type } from './types.js';
|
|
8
|
+
import { assert, ok } from './util.js';
|
|
9
|
+
describe('Project', function () {
|
|
10
|
+
it('can load the GML spec', async function () {
|
|
11
|
+
const spec = await Native.from(undefined, new Type('Struct'), new Map());
|
|
12
|
+
expect(spec).to.exist;
|
|
13
|
+
// STRUCTS AND CONSTS
|
|
14
|
+
const track = spec.types.get('Struct.Track');
|
|
15
|
+
ok(track);
|
|
16
|
+
ok(track.kind === 'Struct');
|
|
17
|
+
const name = track.getMember('name');
|
|
18
|
+
ok(name);
|
|
19
|
+
expect(name.type.kind).to.equal('String');
|
|
20
|
+
const visible = track.getMember('visible');
|
|
21
|
+
ok(visible);
|
|
22
|
+
expect(visible.type.kind).to.equal('Bool');
|
|
23
|
+
const tracks = track.getMember('tracks');
|
|
24
|
+
ok(tracks);
|
|
25
|
+
expect(tracks.type.kind).to.equal('Array');
|
|
26
|
+
expect(tracks.type.items[0].kind).to.equal('Struct');
|
|
27
|
+
expect(tracks.type.items[0].type[0]).to.eql(track);
|
|
28
|
+
const keyframes = track.getMember('keyframes');
|
|
29
|
+
ok(keyframes);
|
|
30
|
+
expect(keyframes.type.kind).to.equal('Array');
|
|
31
|
+
expect(keyframes.type.items[0].kind).to.equal('Struct');
|
|
32
|
+
expect(keyframes.type.items[0].type[0]).to.eql(spec.types.get('Struct.Keyframe'));
|
|
33
|
+
const typeField = track.getMember('type');
|
|
34
|
+
ok(typeField);
|
|
35
|
+
const expectedTypeType = spec.types.get('Constant.SequenceTrackType');
|
|
36
|
+
ok(expectedTypeType);
|
|
37
|
+
ok(typeField.type.type[0] === expectedTypeType);
|
|
38
|
+
ok(expectedTypeType.kind === 'Real');
|
|
39
|
+
// VARIABLES
|
|
40
|
+
const depthSymbol = spec.globalSelf.getMember('depth');
|
|
41
|
+
ok(depthSymbol);
|
|
42
|
+
expect(depthSymbol.type.kind).to.equal('Real');
|
|
43
|
+
// FUNCTIONS
|
|
44
|
+
const scriptExecuteType = spec.types.get('Function.script_execute');
|
|
45
|
+
const scriptExecuteSymbol = spec.globalSelf.getMember('script_execute');
|
|
46
|
+
ok(scriptExecuteSymbol);
|
|
47
|
+
ok(scriptExecuteSymbol.type.type[0] === scriptExecuteType);
|
|
48
|
+
ok(scriptExecuteType);
|
|
49
|
+
ok(scriptExecuteType.kind === 'Function');
|
|
50
|
+
expect(scriptExecuteType.listParameters()).to.have.lengthOf(2);
|
|
51
|
+
expect(scriptExecuteType.listParameters()[0].name).to.equal('scr');
|
|
52
|
+
expect(scriptExecuteType.listParameters()[0].type.type).to.have.lengthOf(3);
|
|
53
|
+
expect(scriptExecuteType.listParameters()[0].type.type[0].kind).to.equal('String');
|
|
54
|
+
expect(scriptExecuteType.listParameters()[0].type.type[1].kind).to.equal('Function');
|
|
55
|
+
expect(scriptExecuteType.listParameters()[0].type.type[2].kind).to.equal('Asset.GMScript');
|
|
56
|
+
expect(scriptExecuteType.listParameters()[1].name).to.equal('...');
|
|
57
|
+
});
|
|
58
|
+
it('can use fallback GmlSpec', async function () {
|
|
59
|
+
await Project.fallbackGmlSpecPath.exists({ assert: true });
|
|
60
|
+
});
|
|
61
|
+
it('can analyze a representative project', async function () {
|
|
62
|
+
const projectDir = 'samples/project';
|
|
63
|
+
const project = await Project.initialize(projectDir);
|
|
64
|
+
ok(project);
|
|
65
|
+
//#region ASSETS
|
|
66
|
+
const script = project.getAssetByName('Script1');
|
|
67
|
+
const scriptFile = script.gmlFile;
|
|
68
|
+
const jsdocs = project.getAssetByName('Jsdocs');
|
|
69
|
+
const jsdocsFile = jsdocs.gmlFile;
|
|
70
|
+
const complexScript = project.getAssetByName('Complicated');
|
|
71
|
+
const complexScriptFile = complexScript.gmlFile;
|
|
72
|
+
const recoveryScript = project.getAssetByName('Recovery');
|
|
73
|
+
const recoveryScriptFile = recoveryScript.gmlFile;
|
|
74
|
+
const obj = project.getAssetByName('o_object');
|
|
75
|
+
const objCreate = obj.gmlFilesArray.find((f) => f.name === 'Create_0');
|
|
76
|
+
const objStep = obj.gmlFilesArray.find((f) => f.name === 'Step_0');
|
|
77
|
+
const parent = project.getAssetByName('o_parent');
|
|
78
|
+
const child = project.getAssetByName('o_child1');
|
|
79
|
+
const grandchild = project.getAssetByName('o_child1_child');
|
|
80
|
+
const child2 = project.getAssetByName('o_child2');
|
|
81
|
+
ok(script);
|
|
82
|
+
ok(scriptFile);
|
|
83
|
+
ok(jsdocs);
|
|
84
|
+
ok(jsdocsFile);
|
|
85
|
+
ok(complexScript);
|
|
86
|
+
ok(complexScriptFile);
|
|
87
|
+
ok(obj);
|
|
88
|
+
ok(objCreate);
|
|
89
|
+
ok(objStep);
|
|
90
|
+
ok(recoveryScript);
|
|
91
|
+
ok(recoveryScriptFile);
|
|
92
|
+
ok(parent);
|
|
93
|
+
ok(child);
|
|
94
|
+
ok(grandchild);
|
|
95
|
+
ok(child2);
|
|
96
|
+
//#endregion ASSETS
|
|
97
|
+
//#region OBJECT INHERITANCE
|
|
98
|
+
// Child1 and Child2 both inherit from Parent
|
|
99
|
+
// Child1Child inherits from Child1
|
|
100
|
+
// Child2 does not call event_inherited in its Create event
|
|
101
|
+
const parentVars = ['parent_var'];
|
|
102
|
+
const childVars = ['child1_var'];
|
|
103
|
+
const grandchildVars = ['child1_child_var'];
|
|
104
|
+
const child2Vars = ['child2_var'];
|
|
105
|
+
// Check inheritance links
|
|
106
|
+
ok(child.parent === parent);
|
|
107
|
+
ok(grandchild.parent === child);
|
|
108
|
+
ok(child2.parent === parent);
|
|
109
|
+
// Check that variables are propery inherited
|
|
110
|
+
expect(parent.instanceType?.listMembers().map((m) => m.name)).to.include.members(parentVars);
|
|
111
|
+
expect(child.instanceType?.listMembers().map((m) => m.name)).to.include.members([...parentVars, ...childVars]);
|
|
112
|
+
expect(grandchild.instanceType?.listMembers().map((m) => m.name)).to.include.members([...parentVars, ...childVars, ...grandchildVars]);
|
|
113
|
+
expect(child2.instanceType?.listMembers().map((m) => m.name)).to.include.members(child2Vars);
|
|
114
|
+
expect(child2.instanceType?.listMembers().map((m) => m.name)).not.to.include.members(parentVars);
|
|
115
|
+
// Check that a reference to the parent_var works in the grandchild
|
|
116
|
+
const grandChildRef = grandchild.gmlFile.getReferenceAt(4, 24);
|
|
117
|
+
ok(grandChildRef);
|
|
118
|
+
expect(grandChildRef.item.name).to.equal('parent_var');
|
|
119
|
+
ok(grandChildRef.item === parent.instanceType.getMember('parent_var'));
|
|
120
|
+
ok(grandChildRef.item.def);
|
|
121
|
+
//#endregion OBJECT INHERITANCE
|
|
122
|
+
// Check fancy assignmnent operators
|
|
123
|
+
const decrementer = script.gmlFile.getReferenceAt(72, 3);
|
|
124
|
+
ok(decrementer);
|
|
125
|
+
const decrementRhs = script.gmlFile.getReferenceAt(72, 19);
|
|
126
|
+
ok(decrementRhs);
|
|
127
|
+
// Check assignment to an unknown variable
|
|
128
|
+
const unknownVar = script.gmlFile.getReferenceAt(76, 13);
|
|
129
|
+
ok(!unknownVar);
|
|
130
|
+
const unknownVarRhs = script.gmlFile.getReferenceAt(76, 24);
|
|
131
|
+
ok(unknownVarRhs);
|
|
132
|
+
// Check reference inside of an accessor
|
|
133
|
+
const accessorRef = script.gmlFile.getReferenceAt(81, 27);
|
|
134
|
+
ok(accessorRef);
|
|
135
|
+
//#region GLOBALVARS
|
|
136
|
+
const globalVarName = 'GLOBAL_SCRIPT_VAR';
|
|
137
|
+
const globalvarDef = scriptFile.getReferenceAt(2, 18);
|
|
138
|
+
const globalvarRef = scriptFile.getReferenceAt(2, 37);
|
|
139
|
+
const otherGlobalvarRef = objStep.getReferenceAt(2, 36);
|
|
140
|
+
ok(globalvarDef);
|
|
141
|
+
ok(globalvarRef);
|
|
142
|
+
ok(otherGlobalvarRef);
|
|
143
|
+
// All refs should point to the same thing
|
|
144
|
+
ok(globalvarDef.item === globalvarRef.item);
|
|
145
|
+
ok(globalvarDef.item === otherGlobalvarRef.item);
|
|
146
|
+
// The definition should exist and be named
|
|
147
|
+
const item = globalvarDef.item;
|
|
148
|
+
ok(item.isRenameable);
|
|
149
|
+
ok(item.def);
|
|
150
|
+
ok(item.name === globalVarName);
|
|
151
|
+
// The globalvar should have appropriate symbol and type info
|
|
152
|
+
ok(item.$tag === 'Sym');
|
|
153
|
+
ok(item.global === true);
|
|
154
|
+
//#endregion GLOBALVARS
|
|
155
|
+
//#region REF RENAMING
|
|
156
|
+
expect(globalvarRef.text).to.equal(globalVarName);
|
|
157
|
+
expect(globalvarRef.isRenameable).to.equal(true);
|
|
158
|
+
//#endregion REF RENAMING
|
|
159
|
+
//#region ROOT SCRIPT SCOPE
|
|
160
|
+
const inRootScriptScope = scriptFile.getInScopeSymbolsAt(762);
|
|
161
|
+
ok(inRootScriptScope.length);
|
|
162
|
+
// Local scope
|
|
163
|
+
const localConstructed = inRootScriptScope.find((id) => id.name === 'const');
|
|
164
|
+
ok(localConstructed);
|
|
165
|
+
ok(localConstructed.local);
|
|
166
|
+
ok(!localConstructed.global);
|
|
167
|
+
// Global scope
|
|
168
|
+
const globalConstructor = inRootScriptScope.find((id) => id.name === 'GlobalConstructor');
|
|
169
|
+
ok(globalConstructor);
|
|
170
|
+
ok(!globalConstructor.local);
|
|
171
|
+
ok(globalConstructor.global);
|
|
172
|
+
ok(globalConstructor.name === 'GlobalConstructor');
|
|
173
|
+
ok(globalConstructor.type.constructs);
|
|
174
|
+
ok(globalConstructor.type.constructs[0].name === 'GlobalConstructor');
|
|
175
|
+
ok(globalConstructor.type.type[0].isFunction);
|
|
176
|
+
expect(globalConstructor.type.kind).to.equal('Function');
|
|
177
|
+
expect(globalConstructor.type.type[0].isConstructor).to.equal(true);
|
|
178
|
+
// Instance scope (should not be found)
|
|
179
|
+
ok(!inRootScriptScope.find((id) => id.name === 'instance_function'));
|
|
180
|
+
// Deeper local scope (should not be found)
|
|
181
|
+
ok(!inRootScriptScope.find((id) => id.name === '_name'));
|
|
182
|
+
//#endregion ROOT SCRIPT SCOPE
|
|
183
|
+
//#region FUNCTION SCOPE
|
|
184
|
+
// Params
|
|
185
|
+
const paramName = '_name';
|
|
186
|
+
const paramRef = scriptFile.getReferenceAt({ line: 18, column: 32 });
|
|
187
|
+
ok(paramRef);
|
|
188
|
+
expect(paramRef.text).to.equal(paramName);
|
|
189
|
+
const param = paramRef.item;
|
|
190
|
+
ok(param);
|
|
191
|
+
ok(param.local);
|
|
192
|
+
ok(param.parameter);
|
|
193
|
+
expect(param.name).to.equal(paramName);
|
|
194
|
+
// Params should be visible in the function scope
|
|
195
|
+
const inFunctionScope = scriptFile.getInScopeSymbolsAt(19, 16);
|
|
196
|
+
ok(inFunctionScope.length);
|
|
197
|
+
ok(inFunctionScope.find((id) => id.name === paramName));
|
|
198
|
+
// And so should local vars
|
|
199
|
+
const inFunctionLocalvar = inFunctionScope.find((id) => id.name === 'local');
|
|
200
|
+
ok(inFunctionLocalvar);
|
|
201
|
+
ok(scriptFile.getReferenceAt(21, 10).item === inFunctionLocalvar);
|
|
202
|
+
//#endregion FUNCTION SCOPE
|
|
203
|
+
//#region INSTANCE SCOPE
|
|
204
|
+
const instanceVarName = 'instance_variable';
|
|
205
|
+
const inInstanceScope = objStep.getReferenceAt(4, 9);
|
|
206
|
+
const objectType = obj.instanceType;
|
|
207
|
+
ok(objectType);
|
|
208
|
+
ok(inInstanceScope);
|
|
209
|
+
expect(inInstanceScope.text).to.equal(instanceVarName);
|
|
210
|
+
ok(inInstanceScope.item.name === instanceVarName);
|
|
211
|
+
ok(inInstanceScope.item.instance);
|
|
212
|
+
// Are functions properly added to self?
|
|
213
|
+
const instanceFunctionName = 'instance_function';
|
|
214
|
+
const instanceFunction = objectType.getMember(instanceFunctionName);
|
|
215
|
+
ok(instanceFunction);
|
|
216
|
+
//#endregion INSTANCE SCOPE
|
|
217
|
+
//#region ENUMS
|
|
218
|
+
const enumName = 'SurpriseEnum';
|
|
219
|
+
const enumMemberName = 'another_surprise';
|
|
220
|
+
const enumDef = scriptFile.getReferenceAt(22, 12);
|
|
221
|
+
const enumMemberDef = scriptFile.getReferenceAt(22, 40);
|
|
222
|
+
ok(enumDef);
|
|
223
|
+
expect(enumDef.text).to.equal(enumName);
|
|
224
|
+
ok(enumDef.item.name === enumName);
|
|
225
|
+
ok(enumMemberDef);
|
|
226
|
+
ok(enumMemberDef.item.name === enumMemberName);
|
|
227
|
+
const enumRef = objCreate.getReferenceAt(3, 23);
|
|
228
|
+
const enumMemberRef = objCreate.getReferenceAt(3, 38);
|
|
229
|
+
ok(enumRef);
|
|
230
|
+
ok(enumRef.item.name === enumName);
|
|
231
|
+
ok(enumMemberRef);
|
|
232
|
+
expect(enumMemberRef.text).to.equal(enumMemberName);
|
|
233
|
+
ok(enumMemberRef.item.name === enumMemberName);
|
|
234
|
+
//#endregion ENUMS
|
|
235
|
+
//#region RECOVERY
|
|
236
|
+
const enumAutocompleteScope = recoveryScriptFile.getScopeRangeAt(3, 22);
|
|
237
|
+
ok(enumAutocompleteScope);
|
|
238
|
+
const enumAutocompleteList = recoveryScriptFile.getInScopeSymbolsAt(3, 22);
|
|
239
|
+
ok(enumAutocompleteList);
|
|
240
|
+
expect(enumAutocompleteList.length).to.equal(2);
|
|
241
|
+
//#endregion RECOVERY
|
|
242
|
+
//#region CONSTRUCTORS
|
|
243
|
+
const constructorName = 'GlobalConstructor';
|
|
244
|
+
const constructorDef = scriptFile.getReferenceAt(18, 17);
|
|
245
|
+
const constructorSymbol = constructorDef.item;
|
|
246
|
+
const constructorType = constructorSymbol.type;
|
|
247
|
+
ok(constructorDef);
|
|
248
|
+
expect(constructorDef.text).to.equal(constructorName);
|
|
249
|
+
ok(constructorSymbol);
|
|
250
|
+
ok(constructorType);
|
|
251
|
+
ok(constructorSymbol.name === constructorName);
|
|
252
|
+
ok(constructorSymbol instanceof Signifier);
|
|
253
|
+
expect(constructorSymbol.type.kind).to.equal('Function');
|
|
254
|
+
expect(constructorSymbol.type.type[0].isConstructor).to.equal(true);
|
|
255
|
+
expect(constructorType.type[0].name).to.equal(constructorName);
|
|
256
|
+
expect(constructorType.type[0].listParameters()).to.have.lengthOf(2);
|
|
257
|
+
expect(constructorType.constructs[0].kind).to.equal('Struct');
|
|
258
|
+
expect(constructorType.constructs[0].name).to.equal(constructorName);
|
|
259
|
+
ok(project.self.getMember(constructorName) === constructorSymbol);
|
|
260
|
+
ok(project.types.get(`Struct.${constructorName}`) ===
|
|
261
|
+
constructorType.constructs[0]);
|
|
262
|
+
//#endregion CONSTRUCTORS
|
|
263
|
+
//#region FUNCTION CALLS
|
|
264
|
+
ok(!scriptFile.getFunctionArgRangeAt(29, 35).hasExpression);
|
|
265
|
+
ok(scriptFile.getFunctionArgRangeAt(41, 50).hasExpression);
|
|
266
|
+
//#endregion FUNCTION CALLS
|
|
267
|
+
//#region DOT ASSIGNMENTS
|
|
268
|
+
const dotAssignedRefName = 'another_instance_variable';
|
|
269
|
+
const dotAssignedRef = objCreate.getReferenceAt(20, 14);
|
|
270
|
+
const dotAssignedType = dotAssignedRef?.item;
|
|
271
|
+
ok(dotAssignedRef);
|
|
272
|
+
expect(dotAssignedRef.text).to.equal(dotAssignedRefName);
|
|
273
|
+
ok(dotAssignedRef.item.name === dotAssignedRefName);
|
|
274
|
+
ok(dotAssignedType);
|
|
275
|
+
ok(dotAssignedType.parent === obj.instanceType?.extends);
|
|
276
|
+
//#endregion DOT ASSIGNMENTS
|
|
277
|
+
//#region FUNCTIONS
|
|
278
|
+
// Check the return type of a function
|
|
279
|
+
const functionDefRef = complexScriptFile.getReferenceAt(119, 22);
|
|
280
|
+
expect((functionDefRef?.item).type.returns[0].kind).to.equal('Array');
|
|
281
|
+
const globalFunction = scriptFile.getReferenceAt(6, 19);
|
|
282
|
+
ok(globalFunction);
|
|
283
|
+
ok(globalFunction.item.name === 'global_function');
|
|
284
|
+
//#endregion FUNCTIONS
|
|
285
|
+
await validateCrossFileDiagnostics(project);
|
|
286
|
+
validateGenerics(project);
|
|
287
|
+
validateWithContexts(project);
|
|
288
|
+
validateFunctionContexts(project);
|
|
289
|
+
validateJsdocs(project);
|
|
290
|
+
validateBschemaConstructor(project);
|
|
291
|
+
await validateAccessorTypes(project);
|
|
292
|
+
// Reprocess a file and ensure that the tests still pass
|
|
293
|
+
await complexScriptFile.reload();
|
|
294
|
+
logger.log('Re-running after reload...');
|
|
295
|
+
validateBschemaConstructor(project);
|
|
296
|
+
});
|
|
297
|
+
it('can sync datafiles', async function () {
|
|
298
|
+
const project = await resetSandbox();
|
|
299
|
+
await project.dir
|
|
300
|
+
.join('datafiles/test-folder/test-file.txt')
|
|
301
|
+
.write('hello');
|
|
302
|
+
await project.syncIncludedFiles();
|
|
303
|
+
assert(project.datafiles.find((f) => f.name === 'test-file.txt' && f.filePath === 'datafiles/test-folder'));
|
|
304
|
+
});
|
|
305
|
+
xit('can parse sample project', async function () {
|
|
306
|
+
const projectDir = process.env.GML_PARSER_SAMPLE_PROJECT_DIR;
|
|
307
|
+
ok(projectDir, 'A dotenv file should provide a path to a full sample project, as env var GML_PARSER_SAMPLE_PROJECT_DIR');
|
|
308
|
+
const project = await Project.initialize(projectDir);
|
|
309
|
+
});
|
|
310
|
+
});
|
|
311
|
+
function validateGenerics(project) {
|
|
312
|
+
const scriptFile = project.getAssetByName('Generics').gmlFile;
|
|
313
|
+
const o_object = project.getAssetByName('o_object');
|
|
314
|
+
// SIMPLE IDENTIFY FUNCTION
|
|
315
|
+
const identifyFunc = scriptFile.getReferenceAt(4, 15).item;
|
|
316
|
+
const returns = identifyFunc.type.returns;
|
|
317
|
+
expect(returns).to.have.lengthOf(1);
|
|
318
|
+
expect(returns[0].type[0].name).to.equal('T');
|
|
319
|
+
const sampleType = scriptFile.getReferenceAt(8, 9).item.type.type[0];
|
|
320
|
+
const returnedSample = scriptFile.getReferenceAt(11, 11).item;
|
|
321
|
+
const returnedSampleType = returnedSample.type.type[0];
|
|
322
|
+
ok(sampleType.kind === returnedSampleType.kind);
|
|
323
|
+
// InstanceType<>
|
|
324
|
+
const returnedInstance = scriptFile.getReferenceAt(24, 7).item.type.type[0];
|
|
325
|
+
ok(returnedInstance.kind === o_object.instanceType.kind);
|
|
326
|
+
// ObjectType<>
|
|
327
|
+
const returnedObject = scriptFile.getReferenceAt(25, 7).item.type.type[0];
|
|
328
|
+
ok(returnedObject.kind === o_object.assetType.kind);
|
|
329
|
+
}
|
|
330
|
+
async function validateCrossFileDiagnostics(project) {
|
|
331
|
+
// In VSCode, we were finding that when a Create event was updated
|
|
332
|
+
// then a struct stored in its variables would have incorrect "missing"
|
|
333
|
+
// properties in the Step of the same object.
|
|
334
|
+
const asset = project.getAssetByName('o_child1_child');
|
|
335
|
+
const createEvent = asset.getEventByName('Create_0');
|
|
336
|
+
const stepEvent = asset.getEventByName('Step_0');
|
|
337
|
+
const propName = 'idle';
|
|
338
|
+
const declaration = createEvent.getReferenceAt(5, 4);
|
|
339
|
+
const reference = stepEvent.getReferenceAt(1, 20);
|
|
340
|
+
const propertyDeclaration = createEvent.getReferenceAt(6, 5);
|
|
341
|
+
const propertyReference = stepEvent.getReferenceAt(1, 25);
|
|
342
|
+
assert(declaration.item === reference.item);
|
|
343
|
+
assert(propertyDeclaration.item === propertyReference.item);
|
|
344
|
+
assert(propertyDeclaration.item.name === propName);
|
|
345
|
+
assert(declaration.item.type.type[0].getMember(propName) ===
|
|
346
|
+
propertyDeclaration.item);
|
|
347
|
+
// Should not have any diagnostics in these files.
|
|
348
|
+
const stepDiagnostics = stepEvent.getDiagnostics().UNDECLARED_VARIABLE_REFERENCE;
|
|
349
|
+
expect(stepDiagnostics).to.have.lengthOf(0);
|
|
350
|
+
// Upon reloading the Create event, should STILL have
|
|
351
|
+
// no diagnostics and the references
|
|
352
|
+
// should all go to the same, *defined* signifiers.
|
|
353
|
+
await createEvent.reload(createEvent.content, { reloadDirty: true });
|
|
354
|
+
const reloadedDeclaration = createEvent.getReferenceAt(5, 4);
|
|
355
|
+
assert(reloadedDeclaration.item === declaration.item);
|
|
356
|
+
const reloadedReference = stepEvent.getReferenceAt(1, 20);
|
|
357
|
+
expect(reloadedReference.item).to.equal(reloadedDeclaration.item);
|
|
358
|
+
const reloadedPropertyDeclaration = createEvent.getReferenceAt(6, 5);
|
|
359
|
+
assert(reloadedPropertyDeclaration.item.name === propName);
|
|
360
|
+
assert(reloadedPropertyDeclaration.item === propertyDeclaration.item);
|
|
361
|
+
const reloadedPropertyReference = stepEvent.getReferenceAt(1, 25);
|
|
362
|
+
assert(reloadedPropertyReference.item === reloadedPropertyDeclaration.item);
|
|
363
|
+
const reloadedStepDiagnostics = stepEvent.getDiagnostics().UNDECLARED_VARIABLE_REFERENCE;
|
|
364
|
+
expect(reloadedStepDiagnostics).to.have.lengthOf(0);
|
|
365
|
+
}
|
|
366
|
+
async function validateAccessorTypes(project) {
|
|
367
|
+
// There was an issue where the type retrieved from an accessor
|
|
368
|
+
// would end up being a *new* type, causing structs to lose
|
|
369
|
+
// properties upon reload
|
|
370
|
+
// The sample case is in the `Reactions` script, where the
|
|
371
|
+
// `_timer` localvar initially has the expected struct type
|
|
372
|
+
// but after reloading it is missing most of its properties
|
|
373
|
+
const reactionTimerFunction = project.self.getMember('ReactionTimer');
|
|
374
|
+
ok(reactionTimerFunction);
|
|
375
|
+
const reactionTimerConstruct = reactionTimerFunction.type.constructs[0];
|
|
376
|
+
ok(reactionTimerConstruct);
|
|
377
|
+
ok(reactionTimerConstruct.name === 'ReactionTimer');
|
|
378
|
+
const expectedMemberNames = [
|
|
379
|
+
'reaction_id',
|
|
380
|
+
'timer',
|
|
381
|
+
'maxtime_min',
|
|
382
|
+
'maxtime_max',
|
|
383
|
+
'maxtime',
|
|
384
|
+
'event_id',
|
|
385
|
+
];
|
|
386
|
+
const assertAllMembersExist = (type) => {
|
|
387
|
+
expectedMemberNames.forEach((name) => {
|
|
388
|
+
ok(type.type[0].getMember(name), `Missing member ${name}`);
|
|
389
|
+
});
|
|
390
|
+
};
|
|
391
|
+
const reactionsAsset = project.getAssetByName('Reactions');
|
|
392
|
+
const reactionsFile = reactionsAsset.gmlFile;
|
|
393
|
+
const functionScope = reactionsFile.getScopeRangeAt(3, 1);
|
|
394
|
+
ok(functionScope);
|
|
395
|
+
const timerVar = functionScope.local.getMember('_timer');
|
|
396
|
+
ok(timerVar);
|
|
397
|
+
ok(timerVar.type.type[0] === reactionTimerConstruct, 'Timer var type is not the expected type');
|
|
398
|
+
let withContext = reactionsFile.getScopeRangeAt(5, 1);
|
|
399
|
+
ok(withContext.self === reactionTimerConstruct);
|
|
400
|
+
assertAllMembersExist(timerVar.type);
|
|
401
|
+
// Reload the file and ensure that the type is still correct
|
|
402
|
+
await reactionsFile.reload();
|
|
403
|
+
const reloadedTimerVar = reactionsFile
|
|
404
|
+
.getScopeRangeAt(3, 1)
|
|
405
|
+
.local.getMember('_timer');
|
|
406
|
+
ok(reloadedTimerVar);
|
|
407
|
+
ok(reloadedTimerVar.type.type[0] === reactionTimerConstruct, 'Timer var type is not the expected type after reload');
|
|
408
|
+
withContext = reactionsFile.getScopeRangeAt(5, 1);
|
|
409
|
+
ok(withContext.self === reactionTimerConstruct);
|
|
410
|
+
assertAllMembersExist(reloadedTimerVar.type);
|
|
411
|
+
}
|
|
412
|
+
function validateFunctionContexts(project) {
|
|
413
|
+
const complicatedScriptFile = project.getAssetByName('Complicated').gmlFile;
|
|
414
|
+
const functionScript = project.getAssetByName('FunctionSelf');
|
|
415
|
+
const functionScriptFile = functionScript.gmlFile;
|
|
416
|
+
ok(functionScript);
|
|
417
|
+
ok(functionScriptFile);
|
|
418
|
+
ok(complicatedScriptFile);
|
|
419
|
+
// GLOBAL CONSTRUCTED CONTEXT
|
|
420
|
+
const bschemaGlobalContext = complicatedScriptFile.getReferenceAt(7, 14).item;
|
|
421
|
+
const functionWithBschemaGlobalContext = functionScriptFile.getScopeRangeAt(2, 32);
|
|
422
|
+
ok(functionWithBschemaGlobalContext &&
|
|
423
|
+
functionWithBschemaGlobalContext.self ===
|
|
424
|
+
bschemaGlobalContext.type.constructs[0]);
|
|
425
|
+
// OBJECT CONTEXT
|
|
426
|
+
const obj = project.getAssetByName('o_object');
|
|
427
|
+
ok(obj && obj.instanceType);
|
|
428
|
+
const functionWithObjectContext = functionScriptFile.getScopeRangeAt(7, 25);
|
|
429
|
+
ok(functionWithObjectContext &&
|
|
430
|
+
functionWithObjectContext.self === obj.assetType);
|
|
431
|
+
// INSTANCE CONTEXT
|
|
432
|
+
const functionWithInstanceContext = functionScriptFile.getScopeRangeAt(12, 27);
|
|
433
|
+
ok(functionWithInstanceContext &&
|
|
434
|
+
functionWithInstanceContext.self === obj.instanceType);
|
|
435
|
+
}
|
|
436
|
+
function validateJsdocs(project) {
|
|
437
|
+
const jsdocsFile = project.getAssetByName('Jsdocs').gmlFile;
|
|
438
|
+
const jsdocs = jsdocsFile.jsdocs;
|
|
439
|
+
expect(jsdocs).to.have.lengthOf(8);
|
|
440
|
+
// Check positions
|
|
441
|
+
let jsdoc = jsdocs[0];
|
|
442
|
+
expect(jsdoc.start.line).to.equal(1);
|
|
443
|
+
expect(jsdoc.start.column).to.equal(1);
|
|
444
|
+
expect(jsdoc.end.line).to.equal(11);
|
|
445
|
+
expect(jsdoc.end.column).to.equal(16);
|
|
446
|
+
expect(jsdoc.params[2].optional).to.equal(true);
|
|
447
|
+
expect(jsdoc.params[2].name.content).to.equal('maybe');
|
|
448
|
+
expect(jsdoc.params[2].name.start.line).to.equal(6);
|
|
449
|
+
expect(jsdoc.params[2].name.end.line).to.equal(6);
|
|
450
|
+
expect(jsdoc.params[2].name.start.column).to.equal(22);
|
|
451
|
+
expect(jsdoc.params[2].name.end.column).to.equal(26);
|
|
452
|
+
expect(jsdoc.params[2].type.content).to.equal('Struct');
|
|
453
|
+
expect(jsdoc.params[2].type.start.line).to.equal(6);
|
|
454
|
+
expect(jsdoc.params[2].type.end.line).to.equal(6);
|
|
455
|
+
expect(jsdoc.params[2].type.start.column).to.equal(13);
|
|
456
|
+
expect(jsdoc.params[2].type.end.column).to.equal(18);
|
|
457
|
+
jsdoc = jsdocs[1];
|
|
458
|
+
expect(jsdoc.start.line).to.equal(13);
|
|
459
|
+
expect(jsdoc.start.column).to.equal(3);
|
|
460
|
+
expect(jsdoc.end.line).to.equal(14);
|
|
461
|
+
expect(jsdoc.end.column).to.equal(21);
|
|
462
|
+
jsdoc = jsdocs[2];
|
|
463
|
+
expect(jsdoc.start.line).to.equal(17);
|
|
464
|
+
expect(jsdoc.start.column).to.equal(3);
|
|
465
|
+
expect(jsdoc.end.line).to.equal(19);
|
|
466
|
+
expect(jsdoc.end.column).to.equal(6);
|
|
467
|
+
jsdoc = jsdocs[3];
|
|
468
|
+
expect(jsdoc.start.line).to.equal(23);
|
|
469
|
+
expect(jsdoc.start.column).to.equal(1);
|
|
470
|
+
expect(jsdoc.end.line).to.equal(34);
|
|
471
|
+
expect(jsdoc.end.column).to.equal(38);
|
|
472
|
+
// This one was misbehaving despite the above tests passing
|
|
473
|
+
const scriptFile = project.getAssetByName('Script1').gmlFile;
|
|
474
|
+
const lastJsdoc = scriptFile.jsdocs.at(-3);
|
|
475
|
+
expect(lastJsdoc.start.line).to.equal(55);
|
|
476
|
+
expect(lastJsdoc.start.column).to.equal(1);
|
|
477
|
+
expect(lastJsdoc.end.line).to.equal(55);
|
|
478
|
+
expect(lastJsdoc.end.column).to.equal(42);
|
|
479
|
+
expect(lastJsdoc.params[0].name.content).to.equal('hello');
|
|
480
|
+
expect(lastJsdoc.params[0].type.start.line).to.equal(55);
|
|
481
|
+
expect(lastJsdoc.params[0].type.end.line).to.equal(55);
|
|
482
|
+
expect(lastJsdoc.params[0].type.start.column).to.equal(11);
|
|
483
|
+
expect(lastJsdoc.params[0].type.end.column).to.equal(34);
|
|
484
|
+
// Make sure that a JSDoc description without a type annotation
|
|
485
|
+
// doesn't cause the type to be forced to `Any`
|
|
486
|
+
const undescribedVar = jsdocsFile.getReferenceAt(42, 11).item;
|
|
487
|
+
ok(undescribedVar);
|
|
488
|
+
expect(undescribedVar.type.kind).to.equal('String');
|
|
489
|
+
const describedVar = jsdocsFile.getReferenceAt(44, 11).item;
|
|
490
|
+
ok(describedVar);
|
|
491
|
+
expect(describedVar.type.kind).to.equal('String');
|
|
492
|
+
}
|
|
493
|
+
function validateWithContexts(project) {
|
|
494
|
+
const complicatedScriptFile = project.getAssetByName('Complicated').gmlFile;
|
|
495
|
+
const withingScript = project.getAssetByName('Withing');
|
|
496
|
+
const withingScriptFile = withingScript.gmlFile;
|
|
497
|
+
ok(withingScript);
|
|
498
|
+
ok(withingScriptFile);
|
|
499
|
+
ok(complicatedScriptFile);
|
|
500
|
+
// WITHING INTO A GLOBAL CONSTRUCTED
|
|
501
|
+
const bschemaGlobalContext = complicatedScriptFile.getReferenceAt(1, 14).item
|
|
502
|
+
.type.type[0];
|
|
503
|
+
ok(bschemaGlobalContext &&
|
|
504
|
+
bschemaGlobalContext.kind === 'Struct' &&
|
|
505
|
+
bschemaGlobalContext.name === 'Bschema');
|
|
506
|
+
const withIntoBschemaGlobal = withingScriptFile.getScopeRangeAt(2, 15);
|
|
507
|
+
ok(withIntoBschemaGlobal &&
|
|
508
|
+
withIntoBschemaGlobal.self === bschemaGlobalContext);
|
|
509
|
+
// WITHING INTO AN OBJECT IDENTIFIER
|
|
510
|
+
const obj = project.getAssetByName('o_object');
|
|
511
|
+
ok(obj && obj.instanceType);
|
|
512
|
+
const withIntoObject = withingScriptFile.getScopeRangeAt(6, 16);
|
|
513
|
+
ok(withIntoObject && withIntoObject.self === obj.assetType);
|
|
514
|
+
// TYPE TEXT
|
|
515
|
+
const typeTextRef = withingScriptFile.getReferenceAt(10, 20);
|
|
516
|
+
ok(typeTextRef);
|
|
517
|
+
expect(typeTextRef.text).to.equal('Id.Instance.o_object');
|
|
518
|
+
expect(typeTextRef.isRenameable).to.equal(true);
|
|
519
|
+
expect(typeTextRef.toRenamed('new_name')).to.equal('Id.Instance.new_name');
|
|
520
|
+
// WITHING INTO AN OBJECT INSTANCE
|
|
521
|
+
const instanceVarRef = withingScriptFile.getReferenceAt(11, 11);
|
|
522
|
+
const instanceVar = instanceVarRef.item;
|
|
523
|
+
ok(instanceVar && instanceVar.type.type[0] === obj.instanceType);
|
|
524
|
+
expect(instanceVarRef.text).to.equal('o_instance');
|
|
525
|
+
expect(instanceVarRef.isRenameable).to.equal(true);
|
|
526
|
+
const withIntoInstance = withingScriptFile.getScopeRangeAt(13, 18);
|
|
527
|
+
ok(withIntoInstance && withIntoInstance.self === obj.instanceType);
|
|
528
|
+
// WITHING USING A JSDOC CONTEXT
|
|
529
|
+
const withIntoJsdoc = withingScriptFile.getScopeRangeAt(20, 25);
|
|
530
|
+
ok(withIntoJsdoc && withIntoJsdoc.self === obj.instanceType);
|
|
531
|
+
// WITHING INTO LOCAL STRUCT
|
|
532
|
+
const localStruct = withingScriptFile.getReferenceAt(24, 9).item;
|
|
533
|
+
ok(localStruct && localStruct.type.kind === 'Struct');
|
|
534
|
+
const withIntoLocalStruct = withingScriptFile.getScopeRangeAt(27, 16);
|
|
535
|
+
ok(withIntoLocalStruct &&
|
|
536
|
+
withIntoLocalStruct.self === localStruct.type.type[0]);
|
|
537
|
+
// The following JSDoc was misbehaving at one point...
|
|
538
|
+
const jsdoc = withingScriptFile.jsdocs[0];
|
|
539
|
+
ok(jsdoc);
|
|
540
|
+
expect(jsdoc.type?.content).to.equal('Id.Instance.o_object');
|
|
541
|
+
expect(jsdoc.type?.start.column).to.equal(12);
|
|
542
|
+
}
|
|
543
|
+
function validateBschemaConstructor(project) {
|
|
544
|
+
const complexScript = project.getAssetByName('Complicated');
|
|
545
|
+
const complexScriptFile = complexScript.gmlFile;
|
|
546
|
+
const bschemaGlobal = project.self.getMember('BSCHEMA');
|
|
547
|
+
const bschemaStructType = project.types.get('Struct.Bschema');
|
|
548
|
+
const bschemaGlobalDef = complexScriptFile.getReferenceAt(1, 15);
|
|
549
|
+
const bschemaConstructor = complexScriptFile.getReferenceAt(7, 13)
|
|
550
|
+
?.item;
|
|
551
|
+
const bschemaRoleType = project.types.get('Struct.BschemaRole');
|
|
552
|
+
ok(bschemaGlobal);
|
|
553
|
+
ok(bschemaStructType);
|
|
554
|
+
ok(bschemaStructType.kind === 'Struct');
|
|
555
|
+
ok(bschemaGlobalDef);
|
|
556
|
+
ok(bschemaGlobalDef.item === bschemaGlobal);
|
|
557
|
+
ok(bschemaConstructor);
|
|
558
|
+
ok(bschemaConstructor.type.kind === 'Function');
|
|
559
|
+
expect(bschemaConstructor.type.type[0].name).to.equal('Bschema');
|
|
560
|
+
ok(bschemaConstructor.type.constructs[0] === bschemaStructType);
|
|
561
|
+
ok(bschemaRoleType);
|
|
562
|
+
// Check all of the members of Struct.Bschema.
|
|
563
|
+
// Make sure that the project_setup Bschema field gets typed based on its assignment
|
|
564
|
+
const projectSetupAssignedTo = bschemaConstructor.type.type[0].getParameter(0);
|
|
565
|
+
ok(projectSetupAssignedTo.name === 'project_setup_function');
|
|
566
|
+
// ok(projectSetupType === projectSetupAssignedTo.type);
|
|
567
|
+
// Check the types of all of the fields of the Bschema struct
|
|
568
|
+
const expectedKinds = {
|
|
569
|
+
base: { kind: 'Struct' },
|
|
570
|
+
changes: { kind: 'Any' },
|
|
571
|
+
clear_changes: { kind: 'Function' },
|
|
572
|
+
commit_id_prefix: { kind: 'String' },
|
|
573
|
+
commitId: { kind: 'String' },
|
|
574
|
+
create_commit_id: { kind: 'Function' },
|
|
575
|
+
create_role: { kind: 'Function' },
|
|
576
|
+
force_use_packed: { kind: 'Bool' },
|
|
577
|
+
init: { kind: 'Function' },
|
|
578
|
+
latest_commitId: {
|
|
579
|
+
kinds: ['String', 'Undefined'],
|
|
580
|
+
code: 'String|Undefined',
|
|
581
|
+
},
|
|
582
|
+
latest: { kind: 'String' },
|
|
583
|
+
next_commit_id: { kind: 'Function' },
|
|
584
|
+
packed_commitId: {
|
|
585
|
+
kinds: ['String', 'Undefined'],
|
|
586
|
+
code: 'String|Undefined',
|
|
587
|
+
},
|
|
588
|
+
project_setup: { kind: 'Function' },
|
|
589
|
+
roles: { kind: 'Struct', code: 'Struct<Struct.BschemaRole>' },
|
|
590
|
+
schema_mote_ids: { kind: 'Struct', code: 'Struct<Array<String>>' },
|
|
591
|
+
uid_pools: { kind: 'Struct' },
|
|
592
|
+
};
|
|
593
|
+
for (const [fieldName, info] of Object.entries(expectedKinds)) {
|
|
594
|
+
logger.log('Checking field', fieldName, 'of Bschema');
|
|
595
|
+
const member = bschemaStructType.getMember(fieldName);
|
|
596
|
+
const type = member?.type;
|
|
597
|
+
ok(member, `Expected to find member ${fieldName}`);
|
|
598
|
+
ok(type, `Expected to find type for member ${fieldName}`);
|
|
599
|
+
expect(member.name).to.equal(fieldName);
|
|
600
|
+
if ('kind' in info) {
|
|
601
|
+
expect(type.kind).to.equal(info.kind);
|
|
602
|
+
}
|
|
603
|
+
expect(member.def, 'All members should have a definition location').to
|
|
604
|
+
.exist;
|
|
605
|
+
if ('kinds' in info) {
|
|
606
|
+
expect(type?.type.length).to.equal(info.kinds.length);
|
|
607
|
+
for (const expectedKind of info.kinds) {
|
|
608
|
+
expect(type?.type.some((t) => t.kind === expectedKind), `Type ${expectedKind} not found in Union`).to.be.true;
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
if ('code' in info) {
|
|
612
|
+
expect(type.toFeatherString()).to.equal(info.code);
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
// Deeper checks on the types of some of the fields
|
|
616
|
+
//#region Bschema.schema_mote_ids
|
|
617
|
+
const schemaMoteIds = bschemaStructType.getMember('schema_mote_ids');
|
|
618
|
+
expect(schemaMoteIds.type.kind).to.equal('Struct');
|
|
619
|
+
expect(schemaMoteIds.type.items).to.exist;
|
|
620
|
+
expect(schemaMoteIds.type.items[0].kind).to.equal('Array');
|
|
621
|
+
expect(schemaMoteIds.type.items[0].type[0].items).to.exist;
|
|
622
|
+
expect(schemaMoteIds.type.items[0].type[0].items.kind).to.equal('String');
|
|
623
|
+
expect(schemaMoteIds.type.toFeatherString()).to.equal('Struct<Array<String>>');
|
|
624
|
+
//#endregion Bschema.schema_mote_ids
|
|
625
|
+
//#region Bschema.roles
|
|
626
|
+
const roles = bschemaStructType.getMember('roles');
|
|
627
|
+
expect(roles.type.kind).to.equal('Struct');
|
|
628
|
+
expect(roles.type.items[0]).to.exist;
|
|
629
|
+
expect(roles.type.items[0].kind).to.equal('Struct');
|
|
630
|
+
ok(roles.type.items[0].type[0] === bschemaRoleType);
|
|
631
|
+
//#endregion Bschema.roles
|
|
632
|
+
}
|
|
633
|
+
//# sourceMappingURL=project.test.js.map
|