• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1import {
2    AccessorDeclaration, AllDecorators, append, BinaryOperator, BindingElement, Bundle, cast, ClassDeclaration,
3    ClassElement, ClassExpression, ClassLikeDeclaration, ClassStaticBlockDeclaration, CompilerOptions,
4    CompoundAssignmentOperator, CoreTransformationContext, createExternalHelpersImportDeclarationIfNeeded,
5    createMultiMap, Decorator, EmitResolver, ESMap, ExportAssignment, ExportDeclaration, ExportSpecifier, Expression,
6    filter, FunctionDeclaration, FunctionLikeDeclaration, getAllAccessorDeclarations, getDecorators,
7    getFirstConstructorWithBody, getNamespaceDeclarationNode, getNodeId, getOriginalNode, hasDecorators,
8    hasStaticModifier, hasSyntacticModifier, Identifier, idText, ImportDeclaration, ImportEqualsDeclaration,
9    ImportSpecifier, InitializedPropertyDeclaration, InternalSymbolName, isAutoAccessorPropertyDeclaration,
10    isBindingPattern, isClassStaticBlockDeclaration, isDefaultImport, isExpressionStatement, isGeneratedIdentifier,
11    isIdentifier, isKeyword, isMethodOrAccessor, isNamedExports, isNamedImports, isOmittedExpression,
12    isPrivateIdentifier, isPropertyDeclaration, isStatic, isStringLiteralLike, isSuperCall, LogicalOperatorOrHigher,
13    map, Map, MethodDeclaration, ModifierFlags, NamedImportBindings, NamespaceExport, Node, NodeArray,
14    parameterIsThisKeyword, PrivateIdentifierAccessorDeclaration, PrivateIdentifierAutoAccessorPropertyDeclaration,
15    PrivateIdentifierMethodDeclaration, PropertyDeclaration, skipParentheses, some, SourceFile, Statement,
16    StructDeclaration, SuperCall, SyntaxKind, TransformationContext, VariableDeclaration, VariableStatement,
17} from "../_namespaces/ts";
18
19/** @internal */
20export function getOriginalNodeId(node: Node) {
21    node = getOriginalNode(node);
22    return node ? getNodeId(node) : 0;
23}
24
25/** @internal */
26export interface ExternalModuleInfo {
27    externalImports: (ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration)[]; // imports of other external modules
28    externalHelpersImportDeclaration: ImportDeclaration | undefined; // import of external helpers
29    exportSpecifiers: ESMap<string, ExportSpecifier[]>; // file-local export specifiers by name (no reexports)
30    exportedBindings: Identifier[][]; // exported names of local declarations
31    exportedNames: Identifier[] | undefined; // all exported names in the module, both local and reexported
32    exportEquals: ExportAssignment | undefined; // an export= declaration if one was present
33    hasExportStarsToExportValues: boolean; // whether this module contains export*
34}
35
36function containsDefaultReference(node: NamedImportBindings | undefined) {
37    if (!node) return false;
38    if (!isNamedImports(node)) return false;
39    return some(node.elements, isNamedDefaultReference);
40}
41
42function isNamedDefaultReference(e: ImportSpecifier): boolean {
43    return e.propertyName !== undefined && e.propertyName.escapedText === InternalSymbolName.Default;
44}
45
46/** @internal */
47export function chainBundle(context: CoreTransformationContext, transformSourceFile: (x: SourceFile) => SourceFile): (x: SourceFile | Bundle) => SourceFile | Bundle {
48    return transformSourceFileOrBundle;
49
50    function transformSourceFileOrBundle(node: SourceFile | Bundle) {
51        return node.kind === SyntaxKind.SourceFile ? transformSourceFile(node) : transformBundle(node);
52    }
53
54    function transformBundle(node: Bundle) {
55        return context.factory.createBundle(map(node.sourceFiles, transformSourceFile), node.prepends);
56    }
57}
58
59/** @internal */
60export function getExportNeedsImportStarHelper(node: ExportDeclaration): boolean {
61    return !!getNamespaceDeclarationNode(node);
62}
63
64/** @internal */
65export function getImportNeedsImportStarHelper(node: ImportDeclaration): boolean {
66    if (!!getNamespaceDeclarationNode(node)) {
67        return true;
68    }
69    const bindings = node.importClause && node.importClause.namedBindings;
70    if (!bindings) {
71        return false;
72    }
73    if (!isNamedImports(bindings)) return false;
74    let defaultRefCount = 0;
75    for (const binding of bindings.elements) {
76        if (isNamedDefaultReference(binding)) {
77            defaultRefCount++;
78        }
79    }
80    // Import star is required if there's default named refs mixed with non-default refs, or if theres non-default refs and it has a default import
81    return (defaultRefCount > 0 && defaultRefCount !== bindings.elements.length) || (!!(bindings.elements.length - defaultRefCount) && isDefaultImport(node));
82}
83
84/** @internal */
85export function getImportNeedsImportDefaultHelper(node: ImportDeclaration): boolean {
86    // Import default is needed if there's a default import or a default ref and no other refs (meaning an import star helper wasn't requested)
87    return !getImportNeedsImportStarHelper(node) && (isDefaultImport(node) || (!!node.importClause && isNamedImports(node.importClause.namedBindings!) && containsDefaultReference(node.importClause.namedBindings))); // TODO: GH#18217
88}
89
90/** @internal */
91export function collectExternalModuleInfo(context: TransformationContext, sourceFile: SourceFile, resolver: EmitResolver, compilerOptions: CompilerOptions): ExternalModuleInfo {
92    const externalImports: (ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration)[] = [];
93    const exportSpecifiers = createMultiMap<ExportSpecifier>();
94    const exportedBindings: Identifier[][] = [];
95    const uniqueExports = new Map<string, boolean>();
96    let exportedNames: Identifier[] | undefined;
97    let hasExportDefault = false;
98    let exportEquals: ExportAssignment | undefined;
99    let hasExportStarsToExportValues = false;
100    let hasImportStar = false;
101    let hasImportDefault = false;
102
103    for (const node of sourceFile.statements) {
104        switch (node.kind) {
105            case SyntaxKind.ImportDeclaration:
106                // import "mod"
107                // import x from "mod"
108                // import * as x from "mod"
109                // import { x, y } from "mod"
110                externalImports.push(node as ImportDeclaration);
111                if (!hasImportStar && getImportNeedsImportStarHelper(node as ImportDeclaration)) {
112                    hasImportStar = true;
113                }
114                if (!hasImportDefault && getImportNeedsImportDefaultHelper(node as ImportDeclaration)) {
115                    hasImportDefault = true;
116                }
117                break;
118
119            case SyntaxKind.ImportEqualsDeclaration:
120                if ((node as ImportEqualsDeclaration).moduleReference.kind === SyntaxKind.ExternalModuleReference) {
121                    // import x = require("mod")
122                    externalImports.push(node as ImportEqualsDeclaration);
123                }
124
125                break;
126
127            case SyntaxKind.ExportDeclaration:
128                if ((node as ExportDeclaration).moduleSpecifier) {
129                    if (!(node as ExportDeclaration).exportClause) {
130                        // export * from "mod"
131                        externalImports.push(node as ExportDeclaration);
132                        hasExportStarsToExportValues = true;
133                    }
134                    else {
135                        // export * as ns from "mod"
136                        // export { x, y } from "mod"
137                        externalImports.push(node as ExportDeclaration);
138                        if (isNamedExports((node as ExportDeclaration).exportClause!)) {
139                            addExportedNamesForExportDeclaration(node as ExportDeclaration);
140                        }
141                        else {
142                            const name = ((node as ExportDeclaration).exportClause as NamespaceExport).name;
143                            if (!uniqueExports.get(idText(name))) {
144                                multiMapSparseArrayAdd(exportedBindings, getOriginalNodeId(node), name);
145                                uniqueExports.set(idText(name), true);
146                                exportedNames = append(exportedNames, name);
147                            }
148                            // we use the same helpers for `export * as ns` as we do for `import * as ns`
149                            hasImportStar = true;
150                        }
151                    }
152                }
153                else {
154                    // export { x, y }
155                    addExportedNamesForExportDeclaration(node as ExportDeclaration);
156                }
157                break;
158
159            case SyntaxKind.ExportAssignment:
160                if ((node as ExportAssignment).isExportEquals && !exportEquals) {
161                    // export = x
162                    exportEquals = node as ExportAssignment;
163                }
164                break;
165
166            case SyntaxKind.VariableStatement:
167                if (hasSyntacticModifier(node, ModifierFlags.Export)) {
168                    for (const decl of (node as VariableStatement).declarationList.declarations) {
169                        exportedNames = collectExportedVariableInfo(decl, uniqueExports, exportedNames);
170                    }
171                }
172                break;
173
174            case SyntaxKind.FunctionDeclaration:
175                if (hasSyntacticModifier(node, ModifierFlags.Export)) {
176                    if (hasSyntacticModifier(node, ModifierFlags.Default)) {
177                        // export default function() { }
178                        if (!hasExportDefault) {
179                            multiMapSparseArrayAdd(exportedBindings, getOriginalNodeId(node), context.factory.getDeclarationName(node as FunctionDeclaration));
180                            hasExportDefault = true;
181                        }
182                    }
183                    else {
184                        // export function x() { }
185                        const name = (node as FunctionDeclaration).name!;
186                        if (!uniqueExports.get(idText(name))) {
187                            multiMapSparseArrayAdd(exportedBindings, getOriginalNodeId(node), name);
188                            uniqueExports.set(idText(name), true);
189                            exportedNames = append(exportedNames, name);
190                        }
191                    }
192                }
193                break;
194
195            case SyntaxKind.ClassDeclaration:
196                if (hasSyntacticModifier(node, ModifierFlags.Export)) {
197                    if (hasSyntacticModifier(node, ModifierFlags.Default)) {
198                        // export default class { }
199                        if (!hasExportDefault) {
200                            multiMapSparseArrayAdd(exportedBindings, getOriginalNodeId(node), context.factory.getDeclarationName(node as ClassDeclaration));
201                            hasExportDefault = true;
202                        }
203                    }
204                    else {
205                        // export class x { }
206                        const name = (node as ClassDeclaration).name;
207                        if (name && !uniqueExports.get(idText(name))) {
208                            multiMapSparseArrayAdd(exportedBindings, getOriginalNodeId(node), name);
209                            uniqueExports.set(idText(name), true);
210                            exportedNames = append(exportedNames, name);
211                        }
212                    }
213                }
214                break;
215        }
216    }
217
218    const externalHelpersImportDeclaration = createExternalHelpersImportDeclarationIfNeeded(context.factory, context.getEmitHelperFactory(), sourceFile, compilerOptions, hasExportStarsToExportValues, hasImportStar, hasImportDefault);
219    if (externalHelpersImportDeclaration) {
220        externalImports.unshift(externalHelpersImportDeclaration);
221    }
222
223    return { externalImports, exportSpecifiers, exportEquals, hasExportStarsToExportValues, exportedBindings, exportedNames, externalHelpersImportDeclaration };
224
225    function addExportedNamesForExportDeclaration(node: ExportDeclaration) {
226        for (const specifier of cast(node.exportClause, isNamedExports).elements) {
227            if (resolver.isReferredToAnnotation(specifier) === true) {
228                continue;
229            }
230            if (!uniqueExports.get(idText(specifier.name))) {
231                const name = specifier.propertyName || specifier.name;
232                if (!node.moduleSpecifier) {
233                    exportSpecifiers.add(idText(name), specifier);
234                }
235
236                const decl = resolver.getReferencedImportDeclaration(name)
237                    || resolver.getReferencedValueDeclaration(name);
238
239                if (decl) {
240                    multiMapSparseArrayAdd(exportedBindings, getOriginalNodeId(decl), specifier.name);
241                }
242
243                uniqueExports.set(idText(specifier.name), true);
244                exportedNames = append(exportedNames, specifier.name);
245            }
246        }
247    }
248}
249
250function collectExportedVariableInfo(decl: VariableDeclaration | BindingElement, uniqueExports: ESMap<string, boolean>, exportedNames: Identifier[] | undefined) {
251    if (isBindingPattern(decl.name)) {
252        for (const element of decl.name.elements) {
253            if (!isOmittedExpression(element)) {
254                exportedNames = collectExportedVariableInfo(element, uniqueExports, exportedNames);
255            }
256        }
257    }
258    else if (!isGeneratedIdentifier(decl.name)) {
259        const text = idText(decl.name);
260        if (!uniqueExports.get(text)) {
261            uniqueExports.set(text, true);
262            exportedNames = append(exportedNames, decl.name);
263        }
264    }
265    return exportedNames;
266}
267
268/** Use a sparse array as a multi-map. */
269function multiMapSparseArrayAdd<V>(map: V[][], key: number, value: V): V[] {
270    let values = map[key];
271    if (values) {
272        values.push(value);
273    }
274    else {
275        map[key] = values = [value];
276    }
277    return values;
278}
279
280/**
281 * Used in the module transformer to check if an expression is reasonably without sideeffect,
282 *  and thus better to copy into multiple places rather than to cache in a temporary variable
283 *  - this is mostly subjective beyond the requirement that the expression not be sideeffecting
284 *
285 * @internal
286 */
287export function isSimpleCopiableExpression(expression: Expression) {
288    return isStringLiteralLike(expression) ||
289        expression.kind === SyntaxKind.NumericLiteral ||
290        isKeyword(expression.kind) ||
291        isIdentifier(expression);
292}
293
294/**
295 * A simple inlinable expression is an expression which can be copied into multiple locations
296 * without risk of repeating any sideeffects and whose value could not possibly change between
297 * any such locations
298 *
299 * @internal
300 */
301export function isSimpleInlineableExpression(expression: Expression) {
302    return !isIdentifier(expression) && isSimpleCopiableExpression(expression);
303}
304
305/** @internal */
306export function isCompoundAssignment(kind: BinaryOperator): kind is CompoundAssignmentOperator {
307    return kind >= SyntaxKind.FirstCompoundAssignment
308        && kind <= SyntaxKind.LastCompoundAssignment;
309}
310
311/** @internal */
312export function getNonAssignmentOperatorForCompoundAssignment(kind: CompoundAssignmentOperator): LogicalOperatorOrHigher | SyntaxKind.QuestionQuestionToken {
313    switch (kind) {
314        case SyntaxKind.PlusEqualsToken: return SyntaxKind.PlusToken;
315        case SyntaxKind.MinusEqualsToken: return SyntaxKind.MinusToken;
316        case SyntaxKind.AsteriskEqualsToken: return SyntaxKind.AsteriskToken;
317        case SyntaxKind.AsteriskAsteriskEqualsToken: return SyntaxKind.AsteriskAsteriskToken;
318        case SyntaxKind.SlashEqualsToken: return SyntaxKind.SlashToken;
319        case SyntaxKind.PercentEqualsToken: return SyntaxKind.PercentToken;
320        case SyntaxKind.LessThanLessThanEqualsToken: return SyntaxKind.LessThanLessThanToken;
321        case SyntaxKind.GreaterThanGreaterThanEqualsToken: return SyntaxKind.GreaterThanGreaterThanToken;
322        case SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken: return SyntaxKind.GreaterThanGreaterThanGreaterThanToken;
323        case SyntaxKind.AmpersandEqualsToken: return SyntaxKind.AmpersandToken;
324        case SyntaxKind.BarEqualsToken: return SyntaxKind.BarToken;
325        case SyntaxKind.CaretEqualsToken: return SyntaxKind.CaretToken;
326        case SyntaxKind.BarBarEqualsToken: return SyntaxKind.BarBarToken;
327        case SyntaxKind.AmpersandAmpersandEqualsToken: return SyntaxKind.AmpersandAmpersandToken;
328        case SyntaxKind.QuestionQuestionEqualsToken: return SyntaxKind.QuestionQuestionToken;
329
330    }
331}
332
333/**
334 * @returns Contained super() call from descending into the statement ignoring parentheses, if that call exists.
335 *
336 * @internal
337 */
338export function getSuperCallFromStatement(statement: Statement): SuperCall | undefined {
339    if (!isExpressionStatement(statement)) {
340        return undefined;
341    }
342
343    const expression = skipParentheses(statement.expression);
344    return isSuperCall(expression)
345        ? expression
346        : undefined;
347}
348
349/**
350 * @returns The index (after prologue statements) of a super call, or -1 if not found.
351 *
352 * @internal
353 */
354export function findSuperStatementIndex(statements: NodeArray<Statement>, indexAfterLastPrologueStatement: number) {
355    for (let i = indexAfterLastPrologueStatement; i < statements.length; i += 1) {
356        const statement = statements[i];
357
358        if (getSuperCallFromStatement(statement)) {
359            return i;
360        }
361    }
362
363    return -1;
364}
365
366/**
367 * Gets all the static or all the instance property declarations of a class
368 *
369 * @param node The class node.
370 * @param isStatic A value indicating whether to get properties from the static or instance side of the class.
371 *
372 * @internal
373 */
374export function getProperties(node: ClassExpression | ClassDeclaration | StructDeclaration, requireInitializer: true, isStatic: boolean): readonly InitializedPropertyDeclaration[];
375/** @internal */
376export function getProperties(node: ClassExpression | ClassDeclaration | StructDeclaration, requireInitializer: boolean, isStatic: boolean): readonly PropertyDeclaration[];
377/** @internal */
378export function getProperties(node: ClassExpression | ClassDeclaration | StructDeclaration, requireInitializer: boolean, isStatic: boolean): readonly PropertyDeclaration[] {
379    return filter(node.members, m => isInitializedOrStaticProperty(m, requireInitializer, isStatic)) as PropertyDeclaration[];
380}
381
382function isStaticPropertyDeclarationOrClassStaticBlockDeclaration(element: ClassElement): element is PropertyDeclaration | ClassStaticBlockDeclaration {
383    return isStaticPropertyDeclaration(element) || isClassStaticBlockDeclaration(element);
384}
385
386/** @internal */
387export function getStaticPropertiesAndClassStaticBlock(node: ClassExpression | ClassDeclaration): readonly (PropertyDeclaration | ClassStaticBlockDeclaration)[];
388/** @internal */
389export function getStaticPropertiesAndClassStaticBlock(node: ClassExpression | ClassDeclaration): readonly (PropertyDeclaration | ClassStaticBlockDeclaration)[];
390/** @internal */
391export function getStaticPropertiesAndClassStaticBlock(node: ClassExpression | ClassDeclaration): readonly (PropertyDeclaration | ClassStaticBlockDeclaration)[] {
392    return filter(node.members, isStaticPropertyDeclarationOrClassStaticBlockDeclaration);
393}
394
395/**
396 * Is a class element either a static or an instance property declaration with an initializer?
397 *
398 * @param member The class element node.
399 * @param isStatic A value indicating whether the member should be a static or instance member.
400 */
401function isInitializedOrStaticProperty(member: ClassElement, requireInitializer: boolean, isStatic: boolean) {
402    return isPropertyDeclaration(member)
403        && (!!member.initializer || !requireInitializer)
404        && hasStaticModifier(member) === isStatic;
405}
406
407function isStaticPropertyDeclaration(member: ClassElement) {
408    return isPropertyDeclaration(member) && hasStaticModifier(member);
409}
410
411/**
412 * Gets a value indicating whether a class element is either a static or an instance property declaration with an initializer.
413 *
414 * @param member The class element node.
415 * @param isStatic A value indicating whether the member should be a static or instance member.
416 *
417 * @internal
418 */
419export function isInitializedProperty(member: ClassElement): member is PropertyDeclaration & { initializer: Expression; } {
420    return member.kind === SyntaxKind.PropertyDeclaration
421        && (member as PropertyDeclaration).initializer !== undefined;
422}
423
424/**
425 * Gets a value indicating whether a class element is a private instance method or accessor.
426 *
427 * @param member The class element node.
428 *
429 * @internal
430 */
431export function isNonStaticMethodOrAccessorWithPrivateName(member: ClassElement): member is PrivateIdentifierMethodDeclaration | PrivateIdentifierAccessorDeclaration | PrivateIdentifierAutoAccessorPropertyDeclaration {
432    return !isStatic(member) && (isMethodOrAccessor(member) || isAutoAccessorPropertyDeclaration(member)) && isPrivateIdentifier(member.name);
433}
434
435/**
436 * Gets an array of arrays of decorators for the parameters of a function-like node.
437 * The offset into the result array should correspond to the offset of the parameter.
438 *
439 * @param node The function-like node.
440 */
441function getDecoratorsOfParameters(node: FunctionLikeDeclaration | undefined) {
442    let decorators: (readonly Decorator[] | undefined)[] | undefined;
443    if (node) {
444        const parameters = node.parameters;
445        const firstParameterIsThis = parameters.length > 0 && parameterIsThisKeyword(parameters[0]);
446        const firstParameterOffset = firstParameterIsThis ? 1 : 0;
447        const numParameters = firstParameterIsThis ? parameters.length - 1 : parameters.length;
448        for (let i = 0; i < numParameters; i++) {
449            const parameter = parameters[i + firstParameterOffset];
450            if (decorators || hasDecorators(parameter)) {
451                if (!decorators) {
452                    decorators = new Array(numParameters);
453                }
454
455                decorators[i] = getDecorators(parameter);
456            }
457        }
458    }
459
460    return decorators;
461}
462
463/**
464 * Gets an AllDecorators object containing the decorators for the class and the decorators for the
465 * parameters of the constructor of the class.
466 *
467 * @param node The class node.
468 *
469 * @internal
470 */
471export function getAllDecoratorsOfClass(node: ClassLikeDeclaration): AllDecorators | undefined {
472    const decorators = getDecorators(node);
473    const parameters = getDecoratorsOfParameters(getFirstConstructorWithBody(node));
474    if (!some(decorators) && !some(parameters)) {
475        return undefined;
476    }
477
478    return {
479        decorators,
480        parameters
481    };
482}
483
484/**
485 * Gets an AllDecorators object containing the decorators for the member and its parameters.
486 *
487 * @param parent The class node that contains the member.
488 * @param member The class member.
489 *
490 * @internal
491 */
492export function getAllDecoratorsOfClassElement(member: ClassElement, parent: ClassLikeDeclaration): AllDecorators | undefined {
493    switch (member.kind) {
494        case SyntaxKind.GetAccessor:
495        case SyntaxKind.SetAccessor:
496            return getAllDecoratorsOfAccessors(member as AccessorDeclaration, parent);
497
498        case SyntaxKind.MethodDeclaration:
499            return getAllDecoratorsOfMethod(member as MethodDeclaration);
500
501        case SyntaxKind.PropertyDeclaration:
502            return getAllDecoratorsOfProperty(member as PropertyDeclaration);
503
504        default:
505            return undefined;
506    }
507}
508
509/**
510 * Gets an AllDecorators object containing the decorators for the accessor and its parameters.
511 *
512 * @param parent The class node that contains the accessor.
513 * @param accessor The class accessor member.
514 */
515function getAllDecoratorsOfAccessors(accessor: AccessorDeclaration, parent: ClassExpression | ClassDeclaration | StructDeclaration): AllDecorators | undefined {
516    if (!accessor.body) {
517        return undefined;
518    }
519
520    const { firstAccessor, secondAccessor, getAccessor, setAccessor } = getAllAccessorDeclarations(parent.members, accessor);
521    const firstAccessorWithDecorators =
522        hasDecorators(firstAccessor) ? firstAccessor :
523        secondAccessor && hasDecorators(secondAccessor) ? secondAccessor :
524        undefined;
525
526    if (!firstAccessorWithDecorators || accessor !== firstAccessorWithDecorators) {
527        return undefined;
528    }
529
530    const decorators = getDecorators(firstAccessorWithDecorators);
531    const parameters = getDecoratorsOfParameters(setAccessor);
532    if (!some(decorators) && !some(parameters)) {
533        return undefined;
534    }
535
536    return {
537        decorators,
538        parameters,
539        getDecorators: getAccessor && getDecorators(getAccessor),
540        setDecorators: setAccessor && getDecorators(setAccessor)
541    };
542}
543
544/**
545 * Gets an AllDecorators object containing the decorators for the method and its parameters.
546 *
547 * @param method The class method member.
548 */
549function getAllDecoratorsOfMethod(method: MethodDeclaration): AllDecorators | undefined {
550    if (!method.body) {
551        return undefined;
552    }
553
554    const decorators = getDecorators(method);
555    const parameters = getDecoratorsOfParameters(method);
556    if (!some(decorators) && !some(parameters)) {
557        return undefined;
558    }
559
560    return { decorators, parameters };
561}
562
563/**
564 * Gets an AllDecorators object containing the decorators for the property.
565 *
566 * @param property The class property member.
567 */
568function getAllDecoratorsOfProperty(property: PropertyDeclaration): AllDecorators | undefined {
569    const decorators = getDecorators(property);
570    if (!some(decorators)) {
571        return undefined;
572
573    }
574
575    return { decorators };
576}
577