• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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