UNPKG

12.3 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3exports.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;
4const ts = require("typescript");
5const typescript_1 = require("typescript");
6const plugin_utils_1 = require("./plugin-utils");
7function getDecorators(node) {
8 return (ts.canHaveDecorators(node) && ts.getDecorators(node)) ?? [];
9}
10exports.getDecorators = getDecorators;
11function getModifiers(node) {
12 return (ts.canHaveModifiers(node) && ts.getModifiers(node)) ?? [];
13}
14exports.getModifiers = getModifiers;
15function isArray(type) {
16 const symbol = type.getSymbol();
17 if (!symbol) {
18 return false;
19 }
20 return symbol.getName() === 'Array' && getTypeArguments(type).length === 1;
21}
22exports.isArray = isArray;
23function getTypeArguments(type) {
24 return type.typeArguments || [];
25}
26exports.getTypeArguments = getTypeArguments;
27function isBoolean(type) {
28 return hasFlag(type, typescript_1.TypeFlags.Boolean);
29}
30exports.isBoolean = isBoolean;
31function isString(type) {
32 return hasFlag(type, typescript_1.TypeFlags.String);
33}
34exports.isString = isString;
35function isStringLiteral(type) {
36 return hasFlag(type, typescript_1.TypeFlags.StringLiteral) && !type.isUnion();
37}
38exports.isStringLiteral = isStringLiteral;
39function isBigInt(type) {
40 return hasFlag(type, typescript_1.TypeFlags.BigInt);
41}
42exports.isBigInt = isBigInt;
43function isNumber(type) {
44 return hasFlag(type, typescript_1.TypeFlags.Number);
45}
46exports.isNumber = isNumber;
47function isInterface(type) {
48 return hasObjectFlag(type, typescript_1.ObjectFlags.Interface);
49}
50exports.isInterface = isInterface;
51function 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}
69exports.isEnum = isEnum;
70function isEnumLiteral(type) {
71 return hasFlag(type, typescript_1.TypeFlags.EnumLiteral) && !type.isUnion();
72}
73exports.isEnumLiteral = isEnumLiteral;
74function 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}
82exports.isNull = isNull;
83function 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}
91exports.isUndefined = isUndefined;
92function hasFlag(type, flag) {
93 return (type.flags & flag) === flag;
94}
95exports.hasFlag = hasFlag;
96function hasObjectFlag(type, flag) {
97 return (type.objectFlags & flag) === flag;
98}
99exports.hasObjectFlag = hasObjectFlag;
100function 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}
107exports.getText = getText;
108function 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}
117exports.getDefaultTypeFormatFlags = getDefaultTypeFormatFlags;
118function getDecoratorArguments(decorator) {
119 const callExpression = decorator.expression;
120 return (callExpression && callExpression.arguments) || [];
121}
122exports.getDecoratorArguments = getDecoratorArguments;
123function 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 // When "import * as _" is used
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}
143exports.getDecoratorName = getDecoratorName;
144function 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}
151function getNameFromExpression(expression) {
152 if (expression && expression.kind === typescript_1.SyntaxKind.PropertyAccessExpression) {
153 return expression.name;
154 }
155 return expression;
156}
157function 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}
164exports.getJSDocDescription = getJSDocDescription;
165function hasJSDocTags(node, tagName) {
166 const tags = (0, typescript_1.getJSDocTags)(node);
167 return tags.some((tag) => tagName.includes(tag.tagName.text));
168 // return jsDoc;
169}
170exports.hasJSDocTags = hasJSDocTags;
171function 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}
178exports.getJsDocDeprecation = getJsDocDeprecation;
179function findNullableTypeFromUnion(typeNode, typeChecker) {
180 return typeNode.types.find((tNode) => hasFlag(typeChecker.getTypeAtLocation(tNode), typescript_1.TypeFlags.Null));
181}
182exports.findNullableTypeFromUnion = findNullableTypeFromUnion;
183function hasModifiers(modifiers, toCheck) {
184 if (!modifiers) {
185 return false;
186 }
187 return modifiers.some((modifier) => toCheck.includes(modifier.kind));
188}
189exports.hasModifiers = hasModifiers;
190function hasDecorators(decorators, toCheck) {
191 if (!decorators) {
192 return false;
193 }
194 return decorators.some((decorator) => {
195 return toCheck.includes(getDecoratorName(decorator));
196 });
197}
198exports.hasDecorators = hasDecorators;
199function 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}
213exports.hasImport = hasImport;
214function createImportEquals(f, identifier, from) {
215 return f.createImportEqualsDeclaration(undefined, false, identifier, f.createExternalModuleReference(f.createStringLiteral(from)));
216}
217exports.createImportEquals = createImportEquals;
218function 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}
222exports.createNamedImport = createNamedImport;
223function isCallExpressionOf(name, node) {
224 return ts.isIdentifier(node.expression) && node.expression.text === name;
225}
226exports.isCallExpressionOf = isCallExpressionOf;
227function isNode(value) {
228 return typeof value === 'object' && value.constructor.name === 'NodeObject';
229}
230function 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}
254exports.serializePrimitiveObjectToAst = serializePrimitiveObjectToAst;
255function safelyMergeObjects(f, a, b) {
256 // if both of objects are ObjectLiterals, so merge property by property in compile time
257 // if one or both of expressions not an object literal, produce rest spread and merge in runtime
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}
275exports.safelyMergeObjects = safelyMergeObjects;
276function 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}
300exports.updateDecoratorArguments = updateDecoratorArguments;