@openwebf/webf 0.22.5 → 0.22.8
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/dist/analyzer.js +117 -17
- package/dist/commands.js +25 -6
- package/dist/react.js +47 -2
- package/package.json +3 -1
- package/src/analyzer.ts +145 -10
- package/src/commands.ts +29 -5
- package/src/declaration.ts +2 -0
- package/src/react.ts +53 -4
- package/templates/react.component.tsx.tpl +57 -6
- package/test/union-types-jsdoc.test.ts +168 -0
- package/dist/analyzer_original.js +0 -467
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { analyzer, clearCaches, UnionTypeCollector, ParameterType } from '../src/analyzer';
|
|
2
|
+
import { generateReactComponent } from '../src/react';
|
|
3
|
+
import { IDLBlob } from '../src/IDLBlob';
|
|
4
|
+
import { ClassObject } from '../src/declaration';
|
|
5
|
+
|
|
6
|
+
describe('Union Types and JSDoc Preservation', () => {
|
|
7
|
+
beforeEach(() => {
|
|
8
|
+
clearCaches();
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
test('should generate union types with quoted string literals and preserve JSDoc @default tags', () => {
|
|
12
|
+
// Create test TypeScript content with union types and JSDoc
|
|
13
|
+
const testContent = `
|
|
14
|
+
/**
|
|
15
|
+
* Table cell component
|
|
16
|
+
*/
|
|
17
|
+
interface WebFTableCellProperties {
|
|
18
|
+
/**
|
|
19
|
+
* Text alignment
|
|
20
|
+
* @default "left"
|
|
21
|
+
*/
|
|
22
|
+
align?: 'left' | 'center' | 'right';
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Cell type (header or data)
|
|
26
|
+
* @default "data"
|
|
27
|
+
*/
|
|
28
|
+
type?: 'header' | 'data';
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Column span
|
|
32
|
+
* @default 1
|
|
33
|
+
*/
|
|
34
|
+
colspan?: number;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
interface WebFTableCellEvents {
|
|
38
|
+
/**
|
|
39
|
+
* Cell click event
|
|
40
|
+
*/
|
|
41
|
+
click: CustomEvent<{row: number, column: number, value: any}>;
|
|
42
|
+
}
|
|
43
|
+
`;
|
|
44
|
+
|
|
45
|
+
// Create IDL blob
|
|
46
|
+
const blob = new IDLBlob('test.d.ts', 'dist', 'table_cell', 'implement');
|
|
47
|
+
blob.raw = testContent;
|
|
48
|
+
|
|
49
|
+
// Analyze the content
|
|
50
|
+
const definedPropertyCollector = {
|
|
51
|
+
properties: new Set<string>(),
|
|
52
|
+
files: new Set<string>(),
|
|
53
|
+
interfaces: new Set<string>()
|
|
54
|
+
};
|
|
55
|
+
const unionTypeCollector: UnionTypeCollector = { types: new Set<ParameterType[]>() };
|
|
56
|
+
|
|
57
|
+
analyzer(blob, definedPropertyCollector, unionTypeCollector);
|
|
58
|
+
|
|
59
|
+
// Generate React component
|
|
60
|
+
const reactCode = generateReactComponent(blob);
|
|
61
|
+
|
|
62
|
+
// Test 1: Check that union types are properly quoted
|
|
63
|
+
expect(reactCode).toContain("align?: 'left' | 'center' | 'right';");
|
|
64
|
+
expect(reactCode).toContain("type?: 'header' | 'data';");
|
|
65
|
+
|
|
66
|
+
// Test 2: Check that JSDoc is preserved with @default tags
|
|
67
|
+
expect(reactCode).toMatch(/\*\s+Text alignment[\s\S]*?\*\s+@default "left"/);
|
|
68
|
+
expect(reactCode).toMatch(/\*\s+Cell type \(header or data\)[\s\S]*?\*\s+@default "data"/);
|
|
69
|
+
|
|
70
|
+
// Test 3: Check that the generated interface has the correct structure
|
|
71
|
+
expect(reactCode).toContain('export interface WebFTableCellProps {');
|
|
72
|
+
expect(reactCode).toContain('colspan?: number;');
|
|
73
|
+
|
|
74
|
+
// Test 4: Verify the component is created with correct props
|
|
75
|
+
expect(reactCode).toContain("attributeProps: [");
|
|
76
|
+
expect(reactCode).toContain("'align',");
|
|
77
|
+
expect(reactCode).toContain("'type',");
|
|
78
|
+
expect(reactCode).toContain("'colspan',");
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
test('should handle complex union types', () => {
|
|
82
|
+
const testContent = `
|
|
83
|
+
interface TestProperties {
|
|
84
|
+
/**
|
|
85
|
+
* Size property
|
|
86
|
+
* @default "medium"
|
|
87
|
+
*/
|
|
88
|
+
size?: 'small' | 'medium' | 'large' | 'xl';
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Status
|
|
92
|
+
* @default "pending"
|
|
93
|
+
*/
|
|
94
|
+
status?: 'pending' | 'active' | 'completed' | 'failed';
|
|
95
|
+
}
|
|
96
|
+
`;
|
|
97
|
+
|
|
98
|
+
const blob = new IDLBlob('test.d.ts', 'dist', 'test', 'implement');
|
|
99
|
+
blob.raw = testContent;
|
|
100
|
+
|
|
101
|
+
const definedPropertyCollector = {
|
|
102
|
+
properties: new Set<string>(),
|
|
103
|
+
files: new Set<string>(),
|
|
104
|
+
interfaces: new Set<string>()
|
|
105
|
+
};
|
|
106
|
+
const unionTypeCollector: UnionTypeCollector = { types: new Set<ParameterType[]>() };
|
|
107
|
+
|
|
108
|
+
analyzer(blob, definedPropertyCollector, unionTypeCollector);
|
|
109
|
+
const reactCode = generateReactComponent(blob);
|
|
110
|
+
|
|
111
|
+
// Check complex union types
|
|
112
|
+
expect(reactCode).toContain("size?: 'small' | 'medium' | 'large' | 'xl';");
|
|
113
|
+
expect(reactCode).toContain("status?: 'pending' | 'active' | 'completed' | 'failed';");
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
test('should handle mixed type properties alongside union types', () => {
|
|
117
|
+
const testContent = `
|
|
118
|
+
interface MixedProperties {
|
|
119
|
+
/**
|
|
120
|
+
* String union type
|
|
121
|
+
* @default "auto"
|
|
122
|
+
*/
|
|
123
|
+
mode?: 'auto' | 'manual' | 'disabled';
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Regular string
|
|
127
|
+
*/
|
|
128
|
+
name?: string;
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Number property
|
|
132
|
+
* @default 42
|
|
133
|
+
*/
|
|
134
|
+
count?: number;
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Boolean property
|
|
138
|
+
* @default true
|
|
139
|
+
*/
|
|
140
|
+
enabled?: boolean;
|
|
141
|
+
}
|
|
142
|
+
`;
|
|
143
|
+
|
|
144
|
+
const blob = new IDLBlob('test.d.ts', 'dist', 'mixed', 'implement');
|
|
145
|
+
blob.raw = testContent;
|
|
146
|
+
|
|
147
|
+
const definedPropertyCollector = {
|
|
148
|
+
properties: new Set<string>(),
|
|
149
|
+
files: new Set<string>(),
|
|
150
|
+
interfaces: new Set<string>()
|
|
151
|
+
};
|
|
152
|
+
const unionTypeCollector: UnionTypeCollector = { types: new Set<ParameterType[]>() };
|
|
153
|
+
|
|
154
|
+
analyzer(blob, definedPropertyCollector, unionTypeCollector);
|
|
155
|
+
const reactCode = generateReactComponent(blob);
|
|
156
|
+
|
|
157
|
+
// Check that different types are handled correctly
|
|
158
|
+
expect(reactCode).toContain("mode?: 'auto' | 'manual' | 'disabled';");
|
|
159
|
+
expect(reactCode).toContain("name?: string;");
|
|
160
|
+
expect(reactCode).toContain("count?: number;");
|
|
161
|
+
expect(reactCode).toContain("enabled?: boolean;");
|
|
162
|
+
|
|
163
|
+
// Check JSDoc preservation
|
|
164
|
+
expect(reactCode).toMatch(/\*\s+String union type[\s\S]*?\*\s+@default "auto"/);
|
|
165
|
+
expect(reactCode).toMatch(/\*\s+Number property[\s\S]*?\*\s+@default 42/);
|
|
166
|
+
expect(reactCode).toMatch(/\*\s+Boolean property[\s\S]*?\*\s+@default true/);
|
|
167
|
+
});
|
|
168
|
+
});
|
|
@@ -1,467 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.analyzer = analyzer;
|
|
37
|
-
exports.buildClassRelationship = buildClassRelationship;
|
|
38
|
-
const typescript_1 = __importStar(require("typescript"));
|
|
39
|
-
const declaration_1 = require("./declaration");
|
|
40
|
-
const utils_1 = require("./utils");
|
|
41
|
-
function analyzer(blob, definedPropertyCollector, unionTypeCollector) {
|
|
42
|
-
const sourceFile = typescript_1.default.createSourceFile(blob.source, blob.raw, typescript_1.ScriptTarget.ES2020);
|
|
43
|
-
blob.objects = sourceFile.statements.map(statement => walkProgram(blob, statement, definedPropertyCollector, unionTypeCollector)).filter(o => {
|
|
44
|
-
return o instanceof declaration_1.ClassObject || o instanceof declaration_1.FunctionObject;
|
|
45
|
-
});
|
|
46
|
-
}
|
|
47
|
-
function buildClassRelationship() {
|
|
48
|
-
const globalClassMap = declaration_1.ClassObject.globalClassMap;
|
|
49
|
-
const globalClassRelationMap = declaration_1.ClassObject.globalClassRelationMap;
|
|
50
|
-
Object.values(globalClassMap).forEach(obj => {
|
|
51
|
-
if (obj.parent) {
|
|
52
|
-
globalClassRelationMap[obj.parent] = globalClassRelationMap[obj.parent] || [];
|
|
53
|
-
globalClassRelationMap[obj.parent].push(obj.name);
|
|
54
|
-
}
|
|
55
|
-
});
|
|
56
|
-
}
|
|
57
|
-
function getInterfaceName(statement) {
|
|
58
|
-
return statement.name.escapedText;
|
|
59
|
-
}
|
|
60
|
-
function getHeritageType(heritage) {
|
|
61
|
-
let expression = heritage.types[0].expression;
|
|
62
|
-
if (expression.kind === typescript_1.default.SyntaxKind.Identifier) {
|
|
63
|
-
return expression.escapedText;
|
|
64
|
-
}
|
|
65
|
-
return null;
|
|
66
|
-
}
|
|
67
|
-
function getMixins(hertage) {
|
|
68
|
-
if (hertage.types.length <= 1)
|
|
69
|
-
return null;
|
|
70
|
-
let mixins = [];
|
|
71
|
-
hertage.types.slice(1).forEach(types => {
|
|
72
|
-
let expression = types.expression;
|
|
73
|
-
if (expression.kind === typescript_1.default.SyntaxKind.Identifier) {
|
|
74
|
-
mixins.push(expression.escapedText);
|
|
75
|
-
}
|
|
76
|
-
});
|
|
77
|
-
return mixins;
|
|
78
|
-
}
|
|
79
|
-
function getPropName(propName, prop) {
|
|
80
|
-
if (propName.kind == typescript_1.default.SyntaxKind.Identifier) {
|
|
81
|
-
return propName.escapedText.toString();
|
|
82
|
-
}
|
|
83
|
-
else if (propName.kind === typescript_1.default.SyntaxKind.StringLiteral) {
|
|
84
|
-
return propName.text;
|
|
85
|
-
}
|
|
86
|
-
else if (propName.kind === typescript_1.default.SyntaxKind.NumericLiteral) {
|
|
87
|
-
return propName.text;
|
|
88
|
-
// @ts-ignore
|
|
89
|
-
}
|
|
90
|
-
else if (propName.kind === typescript_1.default.SyntaxKind.ComputedPropertyName && propName.expression.kind === typescript_1.default.SyntaxKind.PropertyAccessExpression) {
|
|
91
|
-
prop.isSymbol = true;
|
|
92
|
-
// @ts-ignore
|
|
93
|
-
let expression = propName.expression;
|
|
94
|
-
// @ts-ignore
|
|
95
|
-
return `${expression.expression.text}_${expression.name.text}`;
|
|
96
|
-
}
|
|
97
|
-
throw new Error(`prop name: ${typescript_1.default.SyntaxKind[propName.kind]} is not supported`);
|
|
98
|
-
}
|
|
99
|
-
function getParameterName(name) {
|
|
100
|
-
if (name.kind === typescript_1.default.SyntaxKind.Identifier) {
|
|
101
|
-
return name.escapedText.toString();
|
|
102
|
-
}
|
|
103
|
-
return '';
|
|
104
|
-
}
|
|
105
|
-
function getParameterBaseType(type, mode) {
|
|
106
|
-
if (type.kind === typescript_1.default.SyntaxKind.StringKeyword) {
|
|
107
|
-
return declaration_1.FunctionArgumentType.dom_string;
|
|
108
|
-
}
|
|
109
|
-
else if (type.kind === typescript_1.default.SyntaxKind.NumberKeyword) {
|
|
110
|
-
return declaration_1.FunctionArgumentType.double;
|
|
111
|
-
}
|
|
112
|
-
else if (type.kind === typescript_1.default.SyntaxKind.BooleanKeyword) {
|
|
113
|
-
return declaration_1.FunctionArgumentType.boolean;
|
|
114
|
-
}
|
|
115
|
-
else if (type.kind === typescript_1.default.SyntaxKind.AnyKeyword) {
|
|
116
|
-
return declaration_1.FunctionArgumentType.any;
|
|
117
|
-
}
|
|
118
|
-
else if (type.kind === typescript_1.default.SyntaxKind.ObjectKeyword) {
|
|
119
|
-
return declaration_1.FunctionArgumentType.object;
|
|
120
|
-
// @ts-ignore
|
|
121
|
-
}
|
|
122
|
-
else if (type.kind === typescript_1.default.SyntaxKind.VoidKeyword) {
|
|
123
|
-
return declaration_1.FunctionArgumentType.void;
|
|
124
|
-
}
|
|
125
|
-
else if (type.kind === typescript_1.default.SyntaxKind.NullKeyword) {
|
|
126
|
-
return declaration_1.FunctionArgumentType.null;
|
|
127
|
-
}
|
|
128
|
-
else if (type.kind === typescript_1.default.SyntaxKind.UndefinedKeyword) {
|
|
129
|
-
return declaration_1.FunctionArgumentType.undefined;
|
|
130
|
-
}
|
|
131
|
-
else if (type.kind === typescript_1.default.SyntaxKind.TypeReference) {
|
|
132
|
-
let typeReference = type;
|
|
133
|
-
// @ts-ignore
|
|
134
|
-
let identifier = typeReference.typeName.text;
|
|
135
|
-
if (identifier === 'Function') {
|
|
136
|
-
return declaration_1.FunctionArgumentType.function;
|
|
137
|
-
}
|
|
138
|
-
else if (identifier === 'Promise') {
|
|
139
|
-
return declaration_1.FunctionArgumentType.promise;
|
|
140
|
-
}
|
|
141
|
-
else if (identifier === 'JSArrayProtoMethod') {
|
|
142
|
-
return declaration_1.FunctionArgumentType.js_array_proto_methods;
|
|
143
|
-
}
|
|
144
|
-
else if (identifier === 'int') {
|
|
145
|
-
return declaration_1.FunctionArgumentType.int;
|
|
146
|
-
}
|
|
147
|
-
else if (identifier === 'double') {
|
|
148
|
-
return declaration_1.FunctionArgumentType.double;
|
|
149
|
-
}
|
|
150
|
-
else if (identifier === 'NewObject') {
|
|
151
|
-
if (mode)
|
|
152
|
-
mode.newObject = true;
|
|
153
|
-
let argument = typeReference.typeArguments[0];
|
|
154
|
-
// @ts-ignore
|
|
155
|
-
return argument.typeName.text;
|
|
156
|
-
}
|
|
157
|
-
else if (identifier === 'DartImpl') {
|
|
158
|
-
if (mode)
|
|
159
|
-
mode.dartImpl = true;
|
|
160
|
-
let argument = typeReference.typeArguments[0];
|
|
161
|
-
if (argument.kind == typescript_1.default.SyntaxKind.TypeReference) {
|
|
162
|
-
let typeReference = argument;
|
|
163
|
-
// @ts-ignore
|
|
164
|
-
let identifier = typeReference.typeName.text;
|
|
165
|
-
if (identifier == 'DependentsOnLayout') {
|
|
166
|
-
if (mode) {
|
|
167
|
-
mode.layoutDependent = true;
|
|
168
|
-
}
|
|
169
|
-
argument = typeReference.typeArguments[0];
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
// @ts-ignore
|
|
173
|
-
return getParameterBaseType(argument);
|
|
174
|
-
}
|
|
175
|
-
else if (identifier == 'DependentsOnLayout') {
|
|
176
|
-
if (mode)
|
|
177
|
-
mode.layoutDependent = true;
|
|
178
|
-
let argument = typeReference.typeArguments[0];
|
|
179
|
-
argument = typeReference.typeArguments[0];
|
|
180
|
-
// @ts-ignore
|
|
181
|
-
return getParameterBaseType(argument);
|
|
182
|
-
}
|
|
183
|
-
else if (identifier === 'StaticMember') {
|
|
184
|
-
if (mode)
|
|
185
|
-
mode.static = true;
|
|
186
|
-
let argument = typeReference.typeArguments[0];
|
|
187
|
-
// @ts-ignore
|
|
188
|
-
return getParameterBaseType(argument);
|
|
189
|
-
}
|
|
190
|
-
else if (identifier === 'StaticMethod') {
|
|
191
|
-
if (mode)
|
|
192
|
-
mode.staticMethod = true;
|
|
193
|
-
let argument = typeReference.typeArguments[0];
|
|
194
|
-
// @ts-ignore
|
|
195
|
-
return getParameterBaseType(argument);
|
|
196
|
-
}
|
|
197
|
-
else if (identifier.indexOf('SupportAsync') >= 0) {
|
|
198
|
-
if (mode) {
|
|
199
|
-
mode.supportAsync = true;
|
|
200
|
-
if (identifier === "SupportAsyncManual") {
|
|
201
|
-
mode.supportAsyncManual = true;
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
let argument = typeReference.typeArguments[0];
|
|
205
|
-
if (argument.kind == typescript_1.default.SyntaxKind.TypeReference) {
|
|
206
|
-
let typeReference = argument;
|
|
207
|
-
// @ts-ignore
|
|
208
|
-
let identifier = typeReference.typeName.text;
|
|
209
|
-
if (identifier == 'DartImpl') {
|
|
210
|
-
if (mode) {
|
|
211
|
-
mode.dartImpl = true;
|
|
212
|
-
}
|
|
213
|
-
argument = typeReference.typeArguments[0];
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
else if (argument.kind == typescript_1.default.SyntaxKind.ArrayType) {
|
|
217
|
-
let elementType = argument.elementType;
|
|
218
|
-
if (mode)
|
|
219
|
-
mode.supportAsyncArrayValue = true;
|
|
220
|
-
return getParameterBaseType(elementType);
|
|
221
|
-
}
|
|
222
|
-
// @ts-ignore
|
|
223
|
-
return getParameterBaseType(argument);
|
|
224
|
-
}
|
|
225
|
-
return identifier;
|
|
226
|
-
}
|
|
227
|
-
else if (type.kind === typescript_1.default.SyntaxKind.LiteralType) {
|
|
228
|
-
// @ts-ignore
|
|
229
|
-
return getParameterBaseType(type.literal, mode);
|
|
230
|
-
}
|
|
231
|
-
return declaration_1.FunctionArgumentType.any;
|
|
232
|
-
}
|
|
233
|
-
function getParameterType(type, unionTypeCollector, mode) {
|
|
234
|
-
if (type.kind === typescript_1.default.SyntaxKind.ParenthesizedType) {
|
|
235
|
-
let typeNode = type;
|
|
236
|
-
return getParameterType(typeNode.type, unionTypeCollector, mode);
|
|
237
|
-
}
|
|
238
|
-
if (type.kind == typescript_1.default.SyntaxKind.ArrayType) {
|
|
239
|
-
let arrayType = type;
|
|
240
|
-
return {
|
|
241
|
-
isArray: true,
|
|
242
|
-
value: getParameterType(arrayType.elementType, unionTypeCollector, mode)
|
|
243
|
-
};
|
|
244
|
-
}
|
|
245
|
-
else if (type.kind === typescript_1.default.SyntaxKind.UnionType) {
|
|
246
|
-
let node = type;
|
|
247
|
-
let types = node.types;
|
|
248
|
-
let result = {
|
|
249
|
-
isArray: false,
|
|
250
|
-
value: types.map(type => getParameterType(type, unionTypeCollector, mode))
|
|
251
|
-
};
|
|
252
|
-
if ((0, utils_1.isUnionType)(result)) {
|
|
253
|
-
unionTypeCollector.types.add(result.value);
|
|
254
|
-
}
|
|
255
|
-
return result;
|
|
256
|
-
}
|
|
257
|
-
else if (type.kind === typescript_1.default.SyntaxKind.TypeReference) {
|
|
258
|
-
let typeReference = type;
|
|
259
|
-
// @ts-ignore
|
|
260
|
-
let identifier = typeReference.typeName.text;
|
|
261
|
-
if (identifier.indexOf('SupportAsync') >= 0) {
|
|
262
|
-
let argument = typeReference.typeArguments[0];
|
|
263
|
-
if (argument.kind == typescript_1.default.SyntaxKind.UnionType) {
|
|
264
|
-
if (mode) {
|
|
265
|
-
mode.supportAsync = true;
|
|
266
|
-
if (identifier === 'SupportAsyncManual') {
|
|
267
|
-
mode.supportAsyncManual = true;
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
let node = argument;
|
|
271
|
-
let types = node.types;
|
|
272
|
-
let result = {
|
|
273
|
-
isArray: false,
|
|
274
|
-
value: types.map(type => getParameterType(type, unionTypeCollector, mode))
|
|
275
|
-
};
|
|
276
|
-
if ((0, utils_1.isUnionType)(result)) {
|
|
277
|
-
unionTypeCollector.types.add(result.value);
|
|
278
|
-
}
|
|
279
|
-
return result;
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
return {
|
|
284
|
-
isArray: false,
|
|
285
|
-
value: getParameterBaseType(type, mode)
|
|
286
|
-
};
|
|
287
|
-
}
|
|
288
|
-
function paramsNodeToArguments(parameter, unionTypeCollector) {
|
|
289
|
-
let args = new declaration_1.FunctionArguments();
|
|
290
|
-
args.name = getParameterName(parameter.name);
|
|
291
|
-
let typeMode = new declaration_1.ParameterMode();
|
|
292
|
-
args.type = getParameterType(parameter.type, unionTypeCollector, typeMode);
|
|
293
|
-
args.isDotDotDot = !!parameter.dotDotDotToken;
|
|
294
|
-
args.typeMode = typeMode;
|
|
295
|
-
args.required = !parameter.questionToken;
|
|
296
|
-
return args;
|
|
297
|
-
}
|
|
298
|
-
function isParamsReadOnly(m) {
|
|
299
|
-
if (!m.modifiers)
|
|
300
|
-
return false;
|
|
301
|
-
return m.modifiers.some(k => k.kind === typescript_1.default.SyntaxKind.ReadonlyKeyword);
|
|
302
|
-
}
|
|
303
|
-
function walkProgram(blob, statement, definedPropertyCollector, unionTypeCollector) {
|
|
304
|
-
switch (statement.kind) {
|
|
305
|
-
case typescript_1.default.SyntaxKind.InterfaceDeclaration: {
|
|
306
|
-
let interfaceName = getInterfaceName(statement);
|
|
307
|
-
let s = statement;
|
|
308
|
-
let obj = new declaration_1.ClassObject();
|
|
309
|
-
let constructorDefined = false;
|
|
310
|
-
if (s.heritageClauses) {
|
|
311
|
-
let heritage = s.heritageClauses[0];
|
|
312
|
-
let heritageType = getHeritageType(heritage);
|
|
313
|
-
let mixins = getMixins(heritage);
|
|
314
|
-
if (heritageType)
|
|
315
|
-
obj.parent = heritageType.toString();
|
|
316
|
-
if (mixins)
|
|
317
|
-
obj.mixinParent = mixins;
|
|
318
|
-
}
|
|
319
|
-
obj.name = s.name.escapedText.toString();
|
|
320
|
-
if (obj.kind === declaration_1.ClassObjectKind.interface) {
|
|
321
|
-
definedPropertyCollector.interfaces.add('QJS' + interfaceName);
|
|
322
|
-
definedPropertyCollector.files.add(blob.filename);
|
|
323
|
-
definedPropertyCollector.properties.add(interfaceName);
|
|
324
|
-
}
|
|
325
|
-
s.members.forEach(member => {
|
|
326
|
-
var _a;
|
|
327
|
-
switch (member.kind) {
|
|
328
|
-
case typescript_1.default.SyntaxKind.PropertySignature: {
|
|
329
|
-
let prop = new declaration_1.PropsDeclaration();
|
|
330
|
-
let m = member;
|
|
331
|
-
prop.name = getPropName(m.name, prop);
|
|
332
|
-
prop.readonly = isParamsReadOnly(m);
|
|
333
|
-
definedPropertyCollector.properties.add(prop.name);
|
|
334
|
-
let propKind = m.type;
|
|
335
|
-
if (propKind) {
|
|
336
|
-
let mode = new declaration_1.ParameterMode();
|
|
337
|
-
prop.type = getParameterType(propKind, unionTypeCollector, mode);
|
|
338
|
-
prop.typeMode = mode;
|
|
339
|
-
if (member.questionToken) {
|
|
340
|
-
prop.optional = true;
|
|
341
|
-
}
|
|
342
|
-
if (prop.type.value === declaration_1.FunctionArgumentType.function) {
|
|
343
|
-
let f = m.type;
|
|
344
|
-
let functionProps = prop;
|
|
345
|
-
functionProps.args = [];
|
|
346
|
-
f.parameters.forEach(params => {
|
|
347
|
-
let p = paramsNodeToArguments(params, unionTypeCollector);
|
|
348
|
-
functionProps.args.push(p);
|
|
349
|
-
});
|
|
350
|
-
obj.methods.push(functionProps);
|
|
351
|
-
}
|
|
352
|
-
else {
|
|
353
|
-
obj.props.push(prop);
|
|
354
|
-
if (prop.typeMode.supportAsync) {
|
|
355
|
-
// keep asyncProp supportAsync = true
|
|
356
|
-
let asyncProp = Object.assign({}, prop);
|
|
357
|
-
// set prop supportAsync = false
|
|
358
|
-
let syncMode = Object.assign({}, mode);
|
|
359
|
-
syncMode.supportAsync = false;
|
|
360
|
-
mode.supportAsyncManual = false;
|
|
361
|
-
prop.typeMode = syncMode;
|
|
362
|
-
asyncProp.name = asyncProp.name + '_async';
|
|
363
|
-
definedPropertyCollector.properties.add(asyncProp.name);
|
|
364
|
-
asyncProp.async_type = {
|
|
365
|
-
isArray: false,
|
|
366
|
-
value: declaration_1.FunctionArgumentType.promise
|
|
367
|
-
};
|
|
368
|
-
obj.props.push(asyncProp);
|
|
369
|
-
}
|
|
370
|
-
}
|
|
371
|
-
}
|
|
372
|
-
break;
|
|
373
|
-
}
|
|
374
|
-
case typescript_1.default.SyntaxKind.MethodSignature: {
|
|
375
|
-
let m = member;
|
|
376
|
-
let f = new declaration_1.FunctionDeclaration();
|
|
377
|
-
f.name = getPropName(m.name);
|
|
378
|
-
f.args = [];
|
|
379
|
-
m.parameters.forEach(params => {
|
|
380
|
-
let p = paramsNodeToArguments(params, unionTypeCollector);
|
|
381
|
-
f.args.push(p);
|
|
382
|
-
});
|
|
383
|
-
obj.methods.push(f);
|
|
384
|
-
if (m.type) {
|
|
385
|
-
let mode = new declaration_1.ParameterMode();
|
|
386
|
-
f.returnType = getParameterType(m.type, unionTypeCollector, mode);
|
|
387
|
-
// Override the default type for SupportAsync<Type[]> to support ArrayTypes;
|
|
388
|
-
if (mode.supportAsyncArrayValue) {
|
|
389
|
-
f.returnType = {
|
|
390
|
-
isArray: true,
|
|
391
|
-
value: f.returnType
|
|
392
|
-
};
|
|
393
|
-
}
|
|
394
|
-
f.returnTypeMode = mode;
|
|
395
|
-
if (f.returnTypeMode.staticMethod) {
|
|
396
|
-
obj.staticMethods.push(f);
|
|
397
|
-
}
|
|
398
|
-
}
|
|
399
|
-
if ((_a = f.returnTypeMode) === null || _a === void 0 ? void 0 : _a.supportAsync) {
|
|
400
|
-
// keep asyncFunc supportAsync = true
|
|
401
|
-
let asyncFunc = Object.assign({}, f);
|
|
402
|
-
let mode = Object.assign({}, f.returnTypeMode);
|
|
403
|
-
mode.supportAsync = false;
|
|
404
|
-
mode.supportAsyncManual = false;
|
|
405
|
-
f.returnTypeMode = mode;
|
|
406
|
-
asyncFunc.name = getPropName(m.name) + '_async';
|
|
407
|
-
asyncFunc.args = [];
|
|
408
|
-
m.parameters.forEach(params => {
|
|
409
|
-
let p = paramsNodeToArguments(params, unionTypeCollector);
|
|
410
|
-
asyncFunc.args.push(p);
|
|
411
|
-
});
|
|
412
|
-
asyncFunc.async_returnType = {
|
|
413
|
-
isArray: false,
|
|
414
|
-
value: declaration_1.FunctionArgumentType.promise
|
|
415
|
-
};
|
|
416
|
-
obj.methods.push(asyncFunc);
|
|
417
|
-
}
|
|
418
|
-
break;
|
|
419
|
-
}
|
|
420
|
-
case typescript_1.default.SyntaxKind.IndexSignature: {
|
|
421
|
-
let m = member;
|
|
422
|
-
let prop = new declaration_1.IndexedPropertyDeclaration();
|
|
423
|
-
let modifier = m.modifiers;
|
|
424
|
-
prop.readonly = !!(modifier && modifier[0].kind == typescript_1.default.SyntaxKind.ReadonlyKeyword);
|
|
425
|
-
let params = m.parameters;
|
|
426
|
-
prop.indexKeyType = params[0].type.kind === typescript_1.default.SyntaxKind.NumberKeyword ? 'number' : 'string';
|
|
427
|
-
let mode = new declaration_1.ParameterMode();
|
|
428
|
-
prop.type = getParameterType(m.type, unionTypeCollector, mode);
|
|
429
|
-
prop.typeMode = mode;
|
|
430
|
-
obj.indexedProp = prop;
|
|
431
|
-
break;
|
|
432
|
-
}
|
|
433
|
-
case typescript_1.default.SyntaxKind.ConstructSignature: {
|
|
434
|
-
let m = member;
|
|
435
|
-
let c = new declaration_1.FunctionDeclaration();
|
|
436
|
-
c.name = 'constructor';
|
|
437
|
-
c.args = [];
|
|
438
|
-
m.parameters.forEach(params => {
|
|
439
|
-
let p = paramsNodeToArguments(params, unionTypeCollector);
|
|
440
|
-
c.args.push(p);
|
|
441
|
-
});
|
|
442
|
-
c.returnType = getParameterType(m.type, unionTypeCollector);
|
|
443
|
-
obj.construct = c;
|
|
444
|
-
constructorDefined = true;
|
|
445
|
-
break;
|
|
446
|
-
}
|
|
447
|
-
}
|
|
448
|
-
});
|
|
449
|
-
declaration_1.ClassObject.globalClassMap[interfaceName] = obj;
|
|
450
|
-
return obj;
|
|
451
|
-
}
|
|
452
|
-
case typescript_1.default.SyntaxKind.VariableStatement: {
|
|
453
|
-
let declaration = statement.declarationList.declarations[0];
|
|
454
|
-
let methodName = declaration.name.text;
|
|
455
|
-
let type = declaration.type;
|
|
456
|
-
let functionObject = new declaration_1.FunctionObject();
|
|
457
|
-
functionObject.declare = new declaration_1.FunctionDeclaration();
|
|
458
|
-
if ((type === null || type === void 0 ? void 0 : type.kind) == typescript_1.default.SyntaxKind.FunctionType) {
|
|
459
|
-
functionObject.declare.args = type.parameters.map(param => paramsNodeToArguments(param, unionTypeCollector));
|
|
460
|
-
functionObject.declare.returnType = getParameterType(type.type, unionTypeCollector);
|
|
461
|
-
functionObject.declare.name = methodName.toString();
|
|
462
|
-
}
|
|
463
|
-
return functionObject;
|
|
464
|
-
}
|
|
465
|
-
}
|
|
466
|
-
return null;
|
|
467
|
-
}
|