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 { ArkExport, ExportInfo, ExportType } from './ArkExport'; 17import { ArkClass } from './ArkClass'; 18import { ArkFile, Language } from './ArkFile'; 19import { ArkMethod } from './ArkMethod'; 20import { AliasClassSignature, ClassSignature, NamespaceSignature } from './ArkSignature'; 21import { ALL } from '../common/TSConst'; 22import { getColNo, getLineNo, LineCol, setCol, setLine, setLineCol } from '../base/Position'; 23import { ArkBaseModel } from './ArkBaseModel'; 24import { ArkError } from '../common/ArkError'; 25import { NAME_DELIMITER } from '../common/Const'; 26 27/** 28 * @category core/model 29 */ 30export class ArkNamespace extends ArkBaseModel implements ArkExport { 31 private sourceCodes: string[] = ['']; 32 private lineCols: LineCol[] = []; 33 34 private declaringArkFile!: ArkFile; 35 private declaringArkNamespace: ArkNamespace | null = null; 36 37 private declaringInstance!: ArkFile | ArkNamespace; 38 39 private exportInfos: Map<string, ExportInfo> = new Map<string, ExportInfo>(); 40 41 private defaultClass!: ArkClass; 42 43 // name to model 44 private namespaces: Map<string, ArkNamespace> = new Map<string, ArkNamespace>(); // don't contain nested namespace 45 private classes: Map<string, ArkClass> = new Map<string, ArkClass>(); 46 47 private namespaceSignature!: NamespaceSignature; 48 49 private anonymousClassNumber: number = 0; 50 51 constructor() { 52 super(); 53 } 54 55 /** 56 * Returns the program language of the file where this namespace defined. 57 */ 58 public getLanguage(): Language { 59 return this.getDeclaringArkFile().getLanguage(); 60 } 61 62 public addNamespace(namespace: ArkNamespace): void { 63 this.namespaces.set(namespace.getName(), namespace); 64 } 65 66 public getNamespace(namespaceSignature: NamespaceSignature): ArkNamespace | null { 67 const namespaceName = namespaceSignature.getNamespaceName(); 68 return this.getNamespaceWithName(namespaceName); 69 } 70 71 public getNamespaceWithName(namespaceName: string): ArkNamespace | null { 72 return this.namespaces.get(namespaceName) || null; 73 } 74 75 public getNamespaces(): ArkNamespace[] { 76 return Array.from(this.namespaces.values()); 77 } 78 79 public setSignature(namespaceSignature: NamespaceSignature): void { 80 this.namespaceSignature = namespaceSignature; 81 } 82 83 public getSignature(): NamespaceSignature { 84 return this.namespaceSignature; 85 } 86 87 public getNamespaceSignature(): NamespaceSignature { 88 return this.namespaceSignature; 89 } 90 91 public getName(): string { 92 return this.namespaceSignature.getNamespaceName(); 93 } 94 95 public getCode(): string { 96 return this.sourceCodes[0]; 97 } 98 99 public setCode(sourceCode: string): void { 100 this.sourceCodes[0] = sourceCode; 101 } 102 103 /* 104 * Get multiple sourceCodes when the arkNamespace is merged from multiple namespace with the same name 105 */ 106 public getCodes(): string[] { 107 return this.sourceCodes; 108 } 109 110 /* 111 * Set multiple sourceCodes when the arkNamespace is merged from multiple namespace with the same name 112 */ 113 public setCodes(sourceCodes: string[]): void { 114 this.sourceCodes = []; 115 this.sourceCodes.push(...sourceCodes); 116 } 117 118 public addCode(sourceCode: string): void { 119 this.sourceCodes.push(sourceCode); 120 } 121 122 public getLine(): number { 123 return getLineNo(this.lineCols[0]); 124 } 125 126 public setLine(line: number): void { 127 this.lineCols[0] = setLine(this.lineCols[0], line); 128 } 129 130 public getColumn(): number { 131 return getColNo(this.lineCols[0]); 132 } 133 134 public setColumn(column: number): void { 135 this.lineCols[0] = setCol(this.lineCols[0], column); 136 } 137 138 public getLineColPairs(): [number, number][] { 139 const lineColPairs: [number, number][] = []; 140 this.lineCols.forEach(lineCol => { 141 lineColPairs.push([getLineNo(lineCol), getColNo(lineCol)]); 142 }); 143 return lineColPairs; 144 } 145 146 public setLineCols(lineColPairs: [number, number][]): void { 147 this.lineCols = []; 148 lineColPairs.forEach(lineColPair => { 149 this.lineCols.push(setLineCol(lineColPair[0], lineColPair[1])); 150 }); 151 } 152 153 public getDeclaringInstance(): ArkNamespace | ArkFile { 154 return this.declaringInstance; 155 } 156 157 public setDeclaringInstance(declaringInstance: ArkFile | ArkNamespace): void { 158 this.declaringInstance = declaringInstance; 159 } 160 161 public getDeclaringArkFile(): ArkFile { 162 return this.declaringArkFile; 163 } 164 165 public setDeclaringArkFile(declaringArkFile: ArkFile): void { 166 this.declaringArkFile = declaringArkFile; 167 } 168 169 public getDeclaringArkNamespace(): ArkNamespace | null { 170 return this.declaringArkNamespace; 171 } 172 173 public setDeclaringArkNamespace(declaringArkNamespace: ArkNamespace): void { 174 this.declaringArkNamespace = declaringArkNamespace; 175 } 176 177 public getClass(classSignature: ClassSignature): ArkClass | null { 178 const className = classSignature instanceof AliasClassSignature ? classSignature.getOriginName() : classSignature.getClassName(); 179 return this.getClassWithName(className); 180 } 181 182 public getClassWithName(Class: string): ArkClass | null { 183 return this.classes.get(Class) || null; 184 } 185 186 public getClasses(): ArkClass[] { 187 return Array.from(new Set(this.classes.values())); 188 } 189 190 public addArkClass(arkClass: ArkClass, originName?: string): void { 191 const name = originName ?? arkClass.getName(); 192 this.classes.set(name, arkClass); 193 if (!originName && !arkClass.isAnonymousClass()) { 194 const index = name.indexOf(NAME_DELIMITER); 195 if (index > 0) { 196 const originName = name.substring(0, index); 197 this.addArkClass(arkClass, originName); 198 } 199 } 200 } 201 202 public getExportInfos(): ExportInfo[] { 203 const exportInfos: ExportInfo[] = []; 204 this.exportInfos.forEach((value, key) => { 205 if (key !== ALL || value.getFrom()) { 206 exportInfos.push(value); 207 } 208 }); 209 return exportInfos; 210 } 211 212 public getExportInfoBy(name: string): ExportInfo | undefined { 213 return this.exportInfos.get(name); 214 } 215 216 public addExportInfo(exportInfo: ExportInfo): void { 217 this.exportInfos.set(exportInfo.getExportClauseName(), exportInfo); 218 } 219 220 public getDefaultClass(): ArkClass { 221 return this.defaultClass; 222 } 223 224 public setDefaultClass(defaultClass: ArkClass): void { 225 this.defaultClass = defaultClass; 226 } 227 228 public getAllMethodsUnderThisNamespace(): ArkMethod[] { 229 let methods: ArkMethod[] = []; 230 this.classes.forEach(cls => { 231 methods.push(...cls.getMethods()); 232 }); 233 this.namespaces.forEach(ns => { 234 methods.push(...ns.getAllMethodsUnderThisNamespace()); 235 }); 236 return methods; 237 } 238 239 public getAllClassesUnderThisNamespace(): ArkClass[] { 240 let classes: ArkClass[] = []; 241 classes.push(...this.classes.values()); 242 this.namespaces.forEach(ns => { 243 classes.push(...ns.getAllClassesUnderThisNamespace()); 244 }); 245 return classes; 246 } 247 248 public getAllNamespacesUnderThisNamespace(): ArkNamespace[] { 249 let namespaces: ArkNamespace[] = []; 250 namespaces.push(...this.namespaces.values()); 251 this.namespaces.forEach(ns => { 252 namespaces.push(...ns.getAllNamespacesUnderThisNamespace()); 253 }); 254 return namespaces; 255 } 256 257 public getAnonymousClassNumber(): number { 258 return this.anonymousClassNumber++; 259 } 260 261 getExportType(): ExportType { 262 return ExportType.NAME_SPACE; 263 } 264 265 public removeArkClass(arkClass: ArkClass): boolean { 266 let rtn = this.classes.delete(arkClass.getName()); 267 rtn &&= this.getDeclaringArkFile().getScene().removeClass(arkClass); 268 return rtn; 269 } 270 271 public removeNamespace(namespace: ArkNamespace): boolean { 272 let rtn = this.namespaces.delete(namespace.getName()); 273 rtn &&= this.getDeclaringArkFile().getScene().removeNamespace(namespace); 274 return rtn; 275 } 276 277 public validate(): ArkError { 278 return this.validateFields(['declaringArkFile', 'declaringInstance', 'namespaceSignature', 'defaultClass']); 279 } 280} 281