1/* 2 * Copyright (c) 2025 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16import * as arkts from '@koalaui/libarkts'; 17 18export function annotation(name: string): arkts.AnnotationUsage { 19 const ident: arkts.Identifier = arkts.factory.createIdentifier(name).setAnnotationUsage(); 20 const annotation: arkts.AnnotationUsage = arkts.factory.createAnnotationUsage(ident); 21 22 annotation.modifiers = arkts.Es2pandaModifierFlags.MODIFIER_FLAGS_ANNOTATION_USAGE; 23 ident.parent = annotation; 24 25 return annotation; 26} 27 28export function isAnnotation(node: arkts.AnnotationUsage, annoName: string) { 29 return node.expr !== undefined && arkts.isIdentifier(node.expr) && node.expr.name === annoName; 30} 31 32export function removeAnnotationByName( 33 annotations: readonly arkts.AnnotationUsage[], 34 annoName: string 35): arkts.AnnotationUsage[] { 36 return annotations.filter((it) => !isAnnotation(it, annoName)); 37} 38 39export function expectName(node: arkts.AstNode | undefined): string { 40 if (!node) { 41 throw new Error('Expected an identifier, got empty node'); 42 } 43 if (!arkts.isIdentifier(node)) { 44 throw new Error('Expected an identifier, got: ' + arkts.nodeType(node).toString()); 45 } 46 return node.name; 47} 48 49export function mangle(value: string): string { 50 return `__${value}`; 51} 52 53export function backingField(originalName: string): string { 54 return mangle(`backing_${originalName}`); 55} 56 57export function filterDefined<T>(value: (T | undefined)[]): T[] { 58 return value.filter((it: T | undefined): it is T => it != undefined); 59} 60 61export function collect<T>(...value: (ReadonlyArray<T> | T | undefined)[]): T[] { 62 const empty: (T | undefined)[] = []; 63 return filterDefined(empty.concat(...value)); 64} 65 66export function matchPrefix(prefixCollection: (string | RegExp)[], name: string): boolean { 67 for (const prefix of prefixCollection) { 68 let regex: RegExp; 69 70 if (typeof prefix === 'string') { 71 regex = new RegExp('^' + prefix); 72 } else { 73 regex = new RegExp('^' + prefix.source); 74 } 75 76 if (regex.test(name)) { 77 return true; 78 } 79 } 80 return false; 81} 82 83export function updateStructMetadata( 84 structInfo: arkts.StructInfo, 85 propertyName: string, 86 properties: string[], 87 modifiers: arkts.Es2pandaModifierFlags, 88 hasStateManagementType?: boolean 89): arkts.StructInfo { 90 const metadata: Record<string, arkts.StructVariableMetadata> = structInfo.metadata ?? {}; 91 metadata[propertyName] = { 92 name: propertyName, 93 properties, 94 modifiers, 95 hasStateManagementType, 96 }; 97 structInfo.metadata = metadata; 98 return structInfo; 99} 100 101export function moveToFront<T>(arr: T[], idx: number): T[] { 102 if (idx < 0 || idx >= arr.length) { 103 throw new Error(`Index ${idx} is out of bounds for array of length ${arr.length}`); 104 } 105 106 const copy = [...arr]; 107 const [item] = copy.splice(idx, 1); 108 return [item, ...copy]; 109}