1/* 2 * Copyright (c) 2024 - 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 { ArkField, ArkFile, ArkMethod, ArkNamespace, Scene } from 'arkanalyzer'; 17import { ArkClass, ClassCategory } from 'arkanalyzer/lib/core/model/ArkClass'; 18 19export enum MethodCategory { 20 Accessor = 0, 21 ArrowFunction = 1, 22 FunctionExpression = 2, 23 Constructor = 3 24} 25 26export enum MatcherTypes { 27 FILE = 0, 28 NAMESPACE = 1, 29 CLASS = 2, 30 METHOD = 3, 31 FIELD = 4, 32 EXPR = 5 33} 34 35export interface BaseMatcher { 36 [matchFieldName: string]: any; 37} 38 39//TODO: move to FileMatcher.ts 40export interface FileMatcher extends BaseMatcher { 41 readonly matcherType: MatcherTypes.FILE; 42 name?: string; 43} 44 45export interface NamespaceMatcher extends BaseMatcher { 46 readonly matcherType: MatcherTypes.NAMESPACE; 47 name?: string[]; 48 file?: (FileMatcher | ArkFile)[]; 49 namespace?: (NamespaceMatcher | ArkNamespace)[]; 50 isExport?: boolean; 51} 52 53export interface ClassMatcher extends BaseMatcher { 54 readonly matcherType: MatcherTypes.CLASS; 55 name?: string[]; 56 file?: (FileMatcher | ArkFile)[]; 57 namespace?: (NamespaceMatcher | ArkNamespace)[]; 58 category?: ClassCategory[]; 59 isAbstract?: boolean; 60 isExport?: boolean; 61 extends?: (ClassMatcher | ArkClass)[]; 62 implements?: (ClassMatcher | ArkClass)[]; 63 hasViewTree?: boolean; 64} 65 66export interface MethodMatcher extends BaseMatcher { 67 readonly matcherType: MatcherTypes.METHOD; 68 name?: string[]; 69 file?: (FileMatcher | ArkFile)[]; 70 namespace?: (NamespaceMatcher | ArkNamespace)[]; 71 class?: (ClassMatcher | ArkClass)[]; 72 category?: MethodCategory[]; 73 decorators?: string[]; 74 isStatic?: boolean; 75 isExport?: boolean; 76 isPublic?: boolean; 77 isPrivate?: boolean; 78 isProtected?: boolean; 79 isAbstract?: boolean; 80 hasViewTree?: boolean; 81 isAnonymous?: boolean; 82} 83 84export interface FieldMatcher extends BaseMatcher { 85 readonly matcherType: MatcherTypes.FIELD; 86 name?: string[]; 87 file?: (FileMatcher | ArkFile)[]; 88 namespace?: (NamespaceMatcher | ArkNamespace)[]; 89 class?: (ClassMatcher | ArkClass)[]; 90 decorators?: string[]; 91 isStatic?: boolean; 92 isPublic?: boolean; 93 isPrivate?: boolean; 94 isProtected?: boolean; 95 isReadonly?: boolean; 96} 97 98export interface MatcherCallback { 99 matcher: BaseMatcher | undefined, 100 callback: Function 101} 102 103export function isMatchedFile(arkFile: ArkFile, matchers: (FileMatcher | ArkFile)[]): boolean { 104 for (const fileMatcher of matchers) { 105 if (fileMatcher instanceof ArkFile) { 106 if (arkFile === fileMatcher) { 107 return true; 108 } 109 } else { 110 if (fileMatcher.name && arkFile.getName() !== fileMatcher.name) { 111 continue; 112 } 113 return true; 114 } 115 } 116 return false; 117} 118 119export function isMatchedNamespace(arkNs: ArkNamespace | null | undefined, matchers: (NamespaceMatcher | ArkNamespace)[]): boolean { 120 if (!arkNs) { 121 return false; 122 } 123 124 for (const nsMatcher of matchers) { 125 if (nsMatcher instanceof ArkNamespace) { 126 if (arkNs === nsMatcher) { 127 return true; 128 } 129 } else { 130 if (nsMatcher.file && !isMatchedFile(arkNs.getDeclaringArkFile(), nsMatcher.file) || 131 nsMatcher.namespace && !isMatchedNamespace(arkNs.getDeclaringArkNamespace(), nsMatcher.namespace) || 132 nsMatcher.name && !nsMatcher.name.includes(arkNs.getName()) || 133 nsMatcher.isExported !== undefined && nsMatcher.isExported !== arkNs.isExport()) { 134 continue; 135 } 136 // todo: 未考虑嵌套ns场景 137 return true; 138 } 139 } 140 return false; 141} 142 143export function isMatchedClass(arkClass: ArkClass | null | undefined, matchers: (ClassMatcher | ArkClass)[]): boolean { 144 if (!arkClass) { 145 return false; 146 } 147 for (const classMatcher of matchers) { 148 if (classMatcher instanceof ArkClass) { 149 if (arkClass === classMatcher) { 150 return true; 151 } 152 } else { 153 if (classMatcher.file && !isMatchedFile(arkClass.getDeclaringArkFile(), classMatcher.file) || 154 classMatcher.namespace && !isMatchedNamespace(arkClass.getDeclaringArkNamespace(), classMatcher.namespace) || 155 classMatcher.name && !classMatcher.name.includes(arkClass.getName()) || 156 classMatcher.category && !classMatcher.category.includes(arkClass.getCategory()) || 157 classMatcher.isAbstract !== undefined && classMatcher.isAbstract !== arkClass.isAbstract() || 158 classMatcher.isExport !== undefined && classMatcher.isExport !== arkClass.isExport() || 159 classMatcher.hasViewTree !== undefined && classMatcher.hasViewTree !== arkClass.hasViewTree() || 160 // classMatcher.implements && !isMatchedClass(arkClass.getImplementedInterfaces(), classMatcher.implements) || 161 classMatcher.extends && !isMatchedClass(arkClass.getSuperClass(), classMatcher.extends)) { 162 continue; 163 } 164 return true; 165 } 166 } 167 return false; 168} 169 170export function isMatchedMethod(arkMethod: ArkMethod | null | undefined, matchers: (MethodMatcher | ArkMethod)[]): boolean { 171 if (!arkMethod) { 172 return false; 173 } 174 for (const mtdMatcher of matchers) { 175 if (mtdMatcher instanceof ArkMethod) { 176 if (mtdMatcher === arkMethod) { 177 return true; 178 } 179 } else { 180 if (mtdMatcher.file && !isMatchedFile(arkMethod.getDeclaringArkFile(), mtdMatcher.file) || 181 mtdMatcher.namespace && !isMatchedNamespace(arkMethod.getDeclaringArkClass().getDeclaringArkNamespace(), mtdMatcher.namespace) || 182 mtdMatcher.class && !isMatchedClass(arkMethod.getDeclaringArkClass(), mtdMatcher.class) || 183 // mtdMatcher.category && !mtdMatcher.category.includes(arkMethod.getCategory()) || 184 mtdMatcher.isAnonymous && !arkMethod.isAnonymousMethod() || 185 mtdMatcher.name && !mtdMatcher.name.includes(arkMethod.getName()) || 186 mtdMatcher.decorators && !arkMethod.getDecorators().some(d => mtdMatcher.decorators!.includes(d.getKind())) || 187 mtdMatcher.isStatic !== undefined && mtdMatcher.isStatic !== arkMethod.isStatic() || 188 mtdMatcher.isExport !== undefined && mtdMatcher.isExport !== arkMethod.isExport() || 189 mtdMatcher.isPublic !== undefined && mtdMatcher.isPublic !== arkMethod.isPublic() || 190 mtdMatcher.isPrivate !== undefined && mtdMatcher.isPrivate !== arkMethod.isPrivate() || 191 mtdMatcher.isProtected !== undefined && mtdMatcher.isProtected !== arkMethod.isProtected() || 192 mtdMatcher.hasViewTree !== undefined && mtdMatcher.hasViewTree !== arkMethod.hasViewTree() || 193 mtdMatcher.isAbstract !== undefined && mtdMatcher.isAbstract !== arkMethod.isAbstract()) { 194 continue; 195 } 196 return true; 197 } 198 } 199 return false; 200} 201 202export function isMatchedField(arkField: ArkField | null | undefined, matchers: (FieldMatcher | ArkField)[]): boolean { 203 if (!arkField) { 204 return false; 205 } 206 for (const fieldMatcher of matchers) { 207 if (fieldMatcher instanceof ArkField) { 208 if (fieldMatcher === arkField) { 209 return true; 210 } 211 } else { 212 if (fieldMatcher.file && !isMatchedFile(arkField.getDeclaringArkClass().getDeclaringArkFile(), fieldMatcher.file) || 213 fieldMatcher.namespace && !isMatchedNamespace(arkField.getDeclaringArkClass().getDeclaringArkNamespace(), fieldMatcher.namespace) || 214 fieldMatcher.class && !isMatchedClass(arkField.getDeclaringArkClass(), fieldMatcher.class) || 215 fieldMatcher.name && !fieldMatcher.name.includes(arkField.getName()) || 216 fieldMatcher.decorators && !arkField.getDecorators().some(d => fieldMatcher.decorators!.includes(d.getKind())) || 217 fieldMatcher.isStatic !== undefined && fieldMatcher.isStatic !== arkField.isStatic() || 218 fieldMatcher.isPublic !== undefined && fieldMatcher.isPublic !== arkField.isPublic() || 219 fieldMatcher.isPrivate !== undefined && fieldMatcher.isPrivate !== arkField.isPrivate() || 220 fieldMatcher.isProtected !== undefined && fieldMatcher.isProtected !== arkField.isProtected()) { 221 continue; 222 } 223 return true; 224 } 225 } 226 return false; 227}