• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 { OptionValues } from 'commander';
17import * as fs from 'fs';
18
19import path from 'path';
20
21export interface ArkUIConfig {
22    components: Array<string>;
23}
24
25interface NoneUIConfig {
26    files: Array<string>;
27}
28
29export class ArkUIConfigUtil {
30    static instance: ArkUIConfigUtil = new ArkUIConfigUtil();
31    constructor() {
32        this.config = JSON.parse(fs.readFileSync('./config/arkui_config.json', 'utf-8'));
33        this.config.components.forEach(c => {
34            this.componentSet.add(c);
35        });
36        this.noneUIconfig = JSON.parse(fs.readFileSync('./config/none_arkui_files.json', 'utf-8'));
37        this.noneUIconfig.files.forEach(f => {
38            this.noneUIFileSet.add(f);
39        });
40    }
41    // ui components
42    private config: ArkUIConfig;
43    // None ui files
44    private noneUIconfig: NoneUIConfig;
45    private noneUIFileSet: Set<string> = new Set();
46    // Full set of component, should be manually mantained by config file
47    private componentSet: Set<string> = new Set();
48    // Component superclass set, generated by traversing the declartion AST
49    private componentSuperclassSet: Set<string> = new Set();
50    // All class/interface name related to component attribute heritage
51    private componentHeritage: Set<string> = new Set();
52    // All implement relationship of component heritage
53    private componentHerirageRelation: Map<string, string> = new Map();
54    // All component filename
55    private componentFiles: Set<string> = new Set();
56    private file2Attrbiute: Map<string, string> = new Map();
57    private shouldNotHaveAttributeModifier: Set<string> = new Set();
58    private _useMemoM3: boolean = false;
59    private _configPath: string = '';
60    get isHdsComponent(): boolean {
61        return this._configPath.length > 0;
62    }
63    get useMemoM3(): boolean {
64        return this._useMemoM3;
65    }
66    public loadConfig(config: OptionValues): void {
67        if (config.useMemoM3) {
68            this._useMemoM3 = true;
69        }
70
71        if (config.configPath != undefined && config.configPath != '') {
72            this._configPath = config.configPath;
73            // exception process: avoid non-existing given path
74            try {
75                this.config = JSON.parse(fs.readFileSync(this._configPath + '/hds_uicomponents.json', 'utf-8'));
76                this.componentSet.clear();
77                this.config.components.forEach(c => {
78                    this.componentSet.add(c);
79                });
80                this.noneUIconfig = JSON.parse(fs.readFileSync(this._configPath + '/hds_non_uicomponents.json', 'utf-8'));
81                this.noneUIFileSet.clear();
82                this.noneUIconfig.files.forEach(f => {
83                    this.noneUIFileSet.add(f);
84                });
85            } catch (error) {
86                this._configPath = '';
87                console.log('Load given hds_uicomponents file failed!', error);
88            }
89        }
90    }
91    private getPureName(name: string): string {
92        return path
93            .basename(name)
94            .replace(/\.d\.e?ts/g, '')
95            .replace(/_/g, '')
96            .toLowerCase();
97    }
98
99    public isRelatedToComponent(name: string): boolean {
100        return this.componentSet.has(name) || this.componentSuperclassSet.has(name);
101    }
102    public isComponent(name: string, subfix: string): boolean {
103        const regSubfix = new RegExp(subfix, 'g');
104        return this.componentSet.has(name.replace(regSubfix, ''));
105    }
106    public addComponentSuperclass(name: string): void {
107        if (!this.isComponent(name, 'Attribute')) {
108            this.componentSuperclassSet.add(name);
109        }
110    }
111    public addComponentAttributeHeritage(name: string[]): void {
112        let prev: string | undefined = undefined;
113        name.forEach(n => {
114            if (prev) {
115                this.componentHerirageRelation.set(prev, n);
116            }
117            prev = n;
118            this.componentHeritage.add(n);
119        });
120        if (name.length == 1) {
121            this.shouldNotHaveAttributeModifier.add(name[0]);
122        }
123    }
124    public getComponentSuperclass(name: string): string | undefined {
125        return this.componentHerirageRelation.get(name);
126    }
127    public isUIHeritage(name: string): boolean {
128        return this.componentHeritage.has(name);
129    }
130    public notUIFile(name: string): boolean {
131        return this.noneUIFileSet.has(this.getPureName(name));
132    }
133    public addComponentFile(name: string): void {
134        this.componentFiles.add(this.getPureName(name));
135    }
136    public isComponentFile(name: string): boolean {
137        return this.componentFiles.has(this.getPureName(name));
138    }
139    public shouldHaveAttributeModifier(name: string): boolean {
140        if (this.isHdsComponent) {
141            return false;
142        }
143        return !this.shouldNotHaveAttributeModifier.has(name) && this.isComponent(name, 'Attribute');
144    }
145}
146
147export default ArkUIConfigUtil.instance;
148