1 | "use strict";
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | exports.updateDecoratorArguments = exports.safelyMergeObjects = exports.serializePrimitiveObjectToAst = exports.isCallExpressionOf = exports.createNamedImport = exports.createImportEquals = exports.hasImport = exports.hasDecorators = exports.hasModifiers = exports.findNullableTypeFromUnion = exports.getJsDocDeprecation = exports.hasJSDocTags = exports.getJSDocDescription = exports.getDecoratorName = exports.getDecoratorArguments = exports.getDefaultTypeFormatFlags = exports.getText = exports.hasObjectFlag = exports.hasFlag = exports.isUndefined = exports.isNull = exports.isEnumLiteral = exports.isEnum = exports.isInterface = exports.isNumber = exports.isBigInt = exports.isStringLiteral = exports.isString = exports.isBoolean = exports.getTypeArguments = exports.isArray = exports.getModifiers = exports.getDecorators = void 0;
|
4 | const ts = require("typescript");
|
5 | const typescript_1 = require("typescript");
|
6 | const plugin_utils_1 = require("./plugin-utils");
|
7 | function getDecorators(node) {
|
8 | return (ts.canHaveDecorators(node) && ts.getDecorators(node)) ?? [];
|
9 | }
|
10 | exports.getDecorators = getDecorators;
|
11 | function getModifiers(node) {
|
12 | return (ts.canHaveModifiers(node) && ts.getModifiers(node)) ?? [];
|
13 | }
|
14 | exports.getModifiers = getModifiers;
|
15 | function isArray(type) {
|
16 | const symbol = type.getSymbol();
|
17 | if (!symbol) {
|
18 | return false;
|
19 | }
|
20 | return symbol.getName() === 'Array' && getTypeArguments(type).length === 1;
|
21 | }
|
22 | exports.isArray = isArray;
|
23 | function getTypeArguments(type) {
|
24 | return type.typeArguments || [];
|
25 | }
|
26 | exports.getTypeArguments = getTypeArguments;
|
27 | function isBoolean(type) {
|
28 | return hasFlag(type, typescript_1.TypeFlags.Boolean);
|
29 | }
|
30 | exports.isBoolean = isBoolean;
|
31 | function isString(type) {
|
32 | return hasFlag(type, typescript_1.TypeFlags.String);
|
33 | }
|
34 | exports.isString = isString;
|
35 | function isStringLiteral(type) {
|
36 | return hasFlag(type, typescript_1.TypeFlags.StringLiteral) && !type.isUnion();
|
37 | }
|
38 | exports.isStringLiteral = isStringLiteral;
|
39 | function isBigInt(type) {
|
40 | return hasFlag(type, typescript_1.TypeFlags.BigInt);
|
41 | }
|
42 | exports.isBigInt = isBigInt;
|
43 | function isNumber(type) {
|
44 | return hasFlag(type, typescript_1.TypeFlags.Number);
|
45 | }
|
46 | exports.isNumber = isNumber;
|
47 | function isInterface(type) {
|
48 | return hasObjectFlag(type, typescript_1.ObjectFlags.Interface);
|
49 | }
|
50 | exports.isInterface = isInterface;
|
51 | function isEnum(type) {
|
52 | const hasEnumFlag = hasFlag(type, typescript_1.TypeFlags.Enum);
|
53 | if (hasEnumFlag) {
|
54 | return true;
|
55 | }
|
56 | if (isEnumLiteral(type)) {
|
57 | return false;
|
58 | }
|
59 | const symbol = type.getSymbol();
|
60 | if (!symbol) {
|
61 | return false;
|
62 | }
|
63 | const valueDeclaration = symbol.valueDeclaration;
|
64 | if (!valueDeclaration) {
|
65 | return false;
|
66 | }
|
67 | return valueDeclaration.kind === typescript_1.SyntaxKind.EnumDeclaration;
|
68 | }
|
69 | exports.isEnum = isEnum;
|
70 | function isEnumLiteral(type) {
|
71 | return hasFlag(type, typescript_1.TypeFlags.EnumLiteral) && !type.isUnion();
|
72 | }
|
73 | exports.isEnumLiteral = isEnumLiteral;
|
74 | function isNull(type) {
|
75 | if (type.isUnion()) {
|
76 | return Boolean(type.types.find((t) => hasFlag(t, typescript_1.TypeFlags.Null)));
|
77 | }
|
78 | else {
|
79 | return hasFlag(type, typescript_1.TypeFlags.Null);
|
80 | }
|
81 | }
|
82 | exports.isNull = isNull;
|
83 | function isUndefined(type) {
|
84 | if (type.isUnion()) {
|
85 | return Boolean(type.types.find((t) => hasFlag(t, typescript_1.TypeFlags.Undefined)));
|
86 | }
|
87 | else {
|
88 | return hasFlag(type, typescript_1.TypeFlags.Undefined);
|
89 | }
|
90 | }
|
91 | exports.isUndefined = isUndefined;
|
92 | function hasFlag(type, flag) {
|
93 | return (type.flags & flag) === flag;
|
94 | }
|
95 | exports.hasFlag = hasFlag;
|
96 | function hasObjectFlag(type, flag) {
|
97 | return (type.objectFlags & flag) === flag;
|
98 | }
|
99 | exports.hasObjectFlag = hasObjectFlag;
|
100 | function getText(type, typeChecker, enclosingNode, typeFormatFlags) {
|
101 | if (!typeFormatFlags) {
|
102 | typeFormatFlags = getDefaultTypeFormatFlags(enclosingNode);
|
103 | }
|
104 | const compilerNode = !enclosingNode ? undefined : enclosingNode;
|
105 | return typeChecker.typeToString(type, compilerNode, typeFormatFlags);
|
106 | }
|
107 | exports.getText = getText;
|
108 | function getDefaultTypeFormatFlags(enclosingNode) {
|
109 | let formatFlags = typescript_1.TypeFormatFlags.UseTypeOfFunction |
|
110 | typescript_1.TypeFormatFlags.NoTruncation |
|
111 | typescript_1.TypeFormatFlags.UseFullyQualifiedType |
|
112 | typescript_1.TypeFormatFlags.WriteTypeArgumentsOfSignature;
|
113 | if (enclosingNode && enclosingNode.kind === typescript_1.SyntaxKind.TypeAliasDeclaration)
|
114 | formatFlags |= typescript_1.TypeFormatFlags.InTypeAlias;
|
115 | return formatFlags;
|
116 | }
|
117 | exports.getDefaultTypeFormatFlags = getDefaultTypeFormatFlags;
|
118 | function getDecoratorArguments(decorator) {
|
119 | const callExpression = decorator.expression;
|
120 | return (callExpression && callExpression.arguments) || [];
|
121 | }
|
122 | exports.getDecoratorArguments = getDecoratorArguments;
|
123 | function getDecoratorName(decorator) {
|
124 | const isDecoratorFactory = decorator.expression.kind === typescript_1.SyntaxKind.CallExpression;
|
125 | if (isDecoratorFactory) {
|
126 | const callExpression = decorator.expression;
|
127 | if (callExpression.expression?.kind === ts.SyntaxKind.PropertyAccessExpression) {
|
128 |
|
129 | const propertyAccessExpression = callExpression.expression;
|
130 | return getIdentifierFromName(propertyAccessExpression.name).getText();
|
131 | }
|
132 | if (callExpression.kind === ts.SyntaxKind.CallExpression) {
|
133 | const identifier = callExpression
|
134 | .expression;
|
135 | if ((0, plugin_utils_1.isDynamicallyAdded)(identifier)) {
|
136 | return undefined;
|
137 | }
|
138 | return getIdentifierFromName(identifier).getText();
|
139 | }
|
140 | }
|
141 | return getIdentifierFromName(decorator.expression).getText();
|
142 | }
|
143 | exports.getDecoratorName = getDecoratorName;
|
144 | function getIdentifierFromName(expression) {
|
145 | const identifier = getNameFromExpression(expression);
|
146 | if (expression && expression.kind !== typescript_1.SyntaxKind.Identifier) {
|
147 | throw new Error();
|
148 | }
|
149 | return identifier;
|
150 | }
|
151 | function getNameFromExpression(expression) {
|
152 | if (expression && expression.kind === typescript_1.SyntaxKind.PropertyAccessExpression) {
|
153 | return expression.name;
|
154 | }
|
155 | return expression;
|
156 | }
|
157 | function getJSDocDescription(node) {
|
158 | const jsDoc = node.jsDoc;
|
159 | if (!jsDoc || !jsDoc[0]) {
|
160 | return undefined;
|
161 | }
|
162 | return (0, typescript_1.getTextOfJSDocComment)(jsDoc[0].comment);
|
163 | }
|
164 | exports.getJSDocDescription = getJSDocDescription;
|
165 | function hasJSDocTags(node, tagName) {
|
166 | const tags = (0, typescript_1.getJSDocTags)(node);
|
167 | return tags.some((tag) => tagName.includes(tag.tagName.text));
|
168 |
|
169 | }
|
170 | exports.hasJSDocTags = hasJSDocTags;
|
171 | function getJsDocDeprecation(node) {
|
172 | const deprecatedTag = (0, typescript_1.getJSDocDeprecatedTag)(node);
|
173 | if (!deprecatedTag) {
|
174 | return undefined;
|
175 | }
|
176 | return (0, typescript_1.getTextOfJSDocComment)(deprecatedTag.comment) || 'deprecated';
|
177 | }
|
178 | exports.getJsDocDeprecation = getJsDocDeprecation;
|
179 | function findNullableTypeFromUnion(typeNode, typeChecker) {
|
180 | return typeNode.types.find((tNode) => hasFlag(typeChecker.getTypeAtLocation(tNode), typescript_1.TypeFlags.Null));
|
181 | }
|
182 | exports.findNullableTypeFromUnion = findNullableTypeFromUnion;
|
183 | function hasModifiers(modifiers, toCheck) {
|
184 | if (!modifiers) {
|
185 | return false;
|
186 | }
|
187 | return modifiers.some((modifier) => toCheck.includes(modifier.kind));
|
188 | }
|
189 | exports.hasModifiers = hasModifiers;
|
190 | function hasDecorators(decorators, toCheck) {
|
191 | if (!decorators) {
|
192 | return false;
|
193 | }
|
194 | return decorators.some((decorator) => {
|
195 | return toCheck.includes(getDecoratorName(decorator));
|
196 | });
|
197 | }
|
198 | exports.hasDecorators = hasDecorators;
|
199 | function hasImport(sf, what) {
|
200 | for (const statement of sf.statements) {
|
201 | if (ts.isImportDeclaration(statement) &&
|
202 | ts.isNamedImports(statement.importClause.namedBindings)) {
|
203 | const bindings = statement.importClause.namedBindings.elements;
|
204 | for (const namedBinding of bindings) {
|
205 | if (namedBinding.name.text === what) {
|
206 | return true;
|
207 | }
|
208 | }
|
209 | }
|
210 | }
|
211 | return false;
|
212 | }
|
213 | exports.hasImport = hasImport;
|
214 | function createImportEquals(f, identifier, from) {
|
215 | return f.createImportEqualsDeclaration(undefined, false, identifier, f.createExternalModuleReference(f.createStringLiteral(from)));
|
216 | }
|
217 | exports.createImportEquals = createImportEquals;
|
218 | function createNamedImport(f, what, from) {
|
219 | const importClause = f.createImportClause(false, undefined, f.createNamedImports(what.map((name) => f.createImportSpecifier(false, undefined, f.createIdentifier(name)))));
|
220 | return f.createImportDeclaration(undefined, importClause, f.createStringLiteral(from));
|
221 | }
|
222 | exports.createNamedImport = createNamedImport;
|
223 | function isCallExpressionOf(name, node) {
|
224 | return ts.isIdentifier(node.expression) && node.expression.text === name;
|
225 | }
|
226 | exports.isCallExpressionOf = isCallExpressionOf;
|
227 | function isNode(value) {
|
228 | return typeof value === 'object' && value.constructor.name === 'NodeObject';
|
229 | }
|
230 | function serializePrimitiveObjectToAst(f, object) {
|
231 | const properties = [];
|
232 | Object.keys(object).forEach((key) => {
|
233 | const value = object[key];
|
234 | if (value === undefined) {
|
235 | return;
|
236 | }
|
237 | let initializer;
|
238 | if (isNode(value)) {
|
239 | initializer = value;
|
240 | }
|
241 | else if (typeof value === 'string') {
|
242 | initializer = f.createStringLiteral(value);
|
243 | }
|
244 | else if (typeof value === 'boolean') {
|
245 | initializer = value ? f.createTrue() : f.createFalse();
|
246 | }
|
247 | else if (typeof value === 'object') {
|
248 | initializer = serializePrimitiveObjectToAst(f, value);
|
249 | }
|
250 | properties.push(f.createPropertyAssignment(key, initializer));
|
251 | });
|
252 | return f.createObjectLiteralExpression(properties);
|
253 | }
|
254 | exports.serializePrimitiveObjectToAst = serializePrimitiveObjectToAst;
|
255 | function safelyMergeObjects(f, a, b) {
|
256 |
|
257 |
|
258 | if (ts.isObjectLiteralExpression(a) && ts.isObjectLiteralExpression(b)) {
|
259 | const aMap = a.properties.reduce((acc, prop) => {
|
260 | acc[prop.name.text] = prop;
|
261 | return acc;
|
262 | }, {});
|
263 | b.properties.forEach((prop) => {
|
264 | aMap[prop.name.text] = prop;
|
265 | }, {});
|
266 | return f.createObjectLiteralExpression(Object.values(aMap));
|
267 | }
|
268 | else {
|
269 | return f.createObjectLiteralExpression([
|
270 | f.createSpreadAssignment(a),
|
271 | f.createSpreadAssignment(b),
|
272 | ]);
|
273 | }
|
274 | }
|
275 | exports.safelyMergeObjects = safelyMergeObjects;
|
276 | function updateDecoratorArguments(f, node, decoratorName, replaceFn) {
|
277 | let updated = false;
|
278 | const nodeOriginalDecorators = getDecorators(node);
|
279 | const decorators = nodeOriginalDecorators.map((decorator) => {
|
280 | if (getDecoratorName(decorator) !== decoratorName) {
|
281 | return decorator;
|
282 | }
|
283 | const decoratorExpression = decorator.expression;
|
284 | updated = true;
|
285 | return f.updateDecorator(decorator, f.updateCallExpression(decoratorExpression, decoratorExpression.expression, decoratorExpression.typeArguments, replaceFn(decoratorExpression.arguments)));
|
286 | });
|
287 | if (!updated) {
|
288 | return node;
|
289 | }
|
290 | if (ts.isClassDeclaration(node)) {
|
291 | return f.updateClassDeclaration(node, [...decorators, ...getModifiers(node)], node.name, node.typeParameters, node.heritageClauses, node.members);
|
292 | }
|
293 | if (ts.isPropertyDeclaration(node)) {
|
294 | return f.updatePropertyDeclaration(node, [...decorators, ...getModifiers(node)], node.name, node.questionToken, node.type, node.initializer);
|
295 | }
|
296 | if (ts.isGetAccessorDeclaration(node)) {
|
297 | return f.updateGetAccessorDeclaration(node, [...decorators, ...getModifiers(node)], node.name, node.parameters, node.type, node.body);
|
298 | }
|
299 | }
|
300 | exports.updateDecoratorArguments = updateDecoratorArguments;
|